Karashevich B.
Karashevich B.

Reputation: 330

C++, how to return base class and then convert it into derived?

So, I've got a function that should return an object of unknown type, say, C or B. I've decided that adding a common base class A and returning it is a good solution. I've added int type field into A so we can differ B objects from C objects.
For example, function itself looks like this:

A f(int x) {
  if (x==0)
    return B();
  else
    return C();
}

And as an example of its usage:

A a=f(0);
B b; C c;
if (a.type==OBJ_TYPE_B)
  b=a;
else
  c=a;

The problem is obvious: explicit conversion from base class to derived isn't allowed. I see two solutions: pointers and references. Pointers are too C-ish, I don't want to use them. I believe C++ has something better. I've also tried using references, but I don't know what to do with references to temporary objects.
Pls help.

Upvotes: 0

Views: 252

Answers (1)

Peter
Peter

Reputation: 36597

Returning a pointer or reference (assuming A is a polymorphic base) are the most basic ways, and reasonably commonly used. It is necessary to ensure the object that is pointed to (or referenced) continues to exist after the function returns - otherwise any attempt by a caller to use it gives undefined behaviour.

Another common requirement is that the lifetime of the object must be managed. For example, if the function creates the object with operator new, the object must be released using operator delete when no longer needed, otherwise the result will be a memory leak. The problem is that the release of the object must be handled somehow by the caller. If the function returns a pointer, that pointer can be stored in a smart pointer (e.g. the templated std::unique_pointer in C++11 or later) which will manage its lifetime. Alternative, the function can be changed to return a smart pointer.

If you use a smart pointer, read its documentation carefully. Some smart pointers have specific constraints on how they can be used. Typically, they make an assumption about how the object they manage was created (so, if the object is created using operator new, the smart pointer's destructor can release the object using operator delete). Releasing an object by a means that is inconsistent with how it was created gives undefined behaviour. Smart pointers also vary in how they permit objects to be handled among themselves (e.g. can only one smart pointer refer to a given object, or many?).

There is nothing "too C ish" about using a pointer - despite what some C++ language zealots or language-religious nuts might tell you. It is a technique, which you have to respect the limits of - and if you get it wrong, expect trouble. And there are other alternatives to consider, such as smart pointers, which have their own advantages and disadvantages.

Upvotes: 1

Related Questions