I have been struggling with this kind of problem for a long time, so I decided to ask here.
class Base {
virtual ~Base();
};
class Derived1 : public Base { ... };
class Derived2 : public Base { ... };
...
// Copies the instance of derived class pointed by the *base pointer
Base* CreateCopy(Base* base);
The method should return a dynamically created copy, or at least store the object on stack in some data structure to avoid "returning address of a temporary" problem.
The naive approach to implement the above method would be using multiple typeids or dynamic_casts in a series of if-statements to check for each possible derived type and then use the new operator.
Is there any other, better approach?
P.S.: I know, that the this problem can be avoided using smart pointers, but I am interested in the minimalistic approach, without a bunch of libraries.
You add a virtual Base* clone() const = 0; in your base class and implement it appropriately in your Derived classes. If your Base is not abstract, you can of course call its copy-constructor, but that's a bit dangerous: If you forget to implement it in a derived class, you'll get (probably unwanted) slicing.
If you don't want to duplicate that code, you can use the CRTP idiom to implement the function via a template:
template <class Derived>
class DerivationHelper : public Base
{
public:
virtual Base* clone() const
{
return new Derived(static_cast<const Derived&>(*this)); // call the copy ctor.
}
};
class Derived1 : public DerivationHelper <Derived1> { ... };
class Derived2 : public DerivationHelper <Derived2> { ... };
An alternative is to have a pure virtual CreateCopy() method in the common base that is implemented in each derived class.
Related
I searched around and seems in order to perform this I need to change my Base class and want to know if this is the best approach.
For example,
I have a Base class:
class Base {}
Then a long line of derived classes:
class Derived_1:: public Base {}
class Derived_2:: public Derived_1{}
...
...
class Derived_n:: public Derived_M{}
And then I have another class:
class DeepCopy
{
Base * basePtr;
public:
DeepCopy(DeepCopy & dc) {}
}
Assuming the Base class and Derived_x class copy constructors are properly coded, what is the best way to write the copy constructor for DeepCopy. How can we know about the class that is in the basePtr of the object we are going to copy?
Only way I can think of is using RTTI, but using a long list of dynamic_casts seems not right. Besides it requires DeepCopy to know about the inheritance hierarchy of Base class.
The other method I saw is here. But it requires Base and Derived classes implement a clone method.
So is there a much easier, standard way of doing this?
You need to use the virtual copy pattern: provide a virtual function in the interface that does the copy and then implement it across the hierarchy:
struct base {
virtual ~base() {} // Remember to provide a virtual destructor
virtual base* clone() const = 0;
};
struct derived : base {
virtual derived* clone() const {
return new derived(*this);
}
};
Then the DeepCopy object just needs to call that function:
class DeepCopy
{
Base * basePtr;
public:
DeepCopy(DeepCopy const & dc) // This should be `const`
: basePtr( dc.basePtr->clone() )
{}
};
Using an approach that employs a clone() function is a good solution. Note using the CRTP (the curiously recurring template pattern) can save you some of the work. The way you do it is by introducing an intermediate level (called BaseCRTP below) which is a template and implements the clone() function. When you derive your actual classes, use them as the template argument of the base they are derived from. They will get the clone() function implemented for them automatically. Make sure the derived classes implement a copy constructor (or be sure the default is what you need).
/* Base class includes pure virtual clone function */
class Base {
public:
virtual ~Base() {}
virtual Base *clone() const = 0;
};
/* Intermediate class that implements CRTP. Use this
* as a base class for any derived class that you want
* to have a clone function.
*/
template <typename Derived>
class BaseCRTP : public Base {
public:
virtual Base *clone() const {
return new Derived(static_cast<Derived const&>(*this));
}
};
/* Derive further classes. Each of them must
* implement a correct copy constructor, because
* that is used by the clone() function automatically.
*/
class Derived1 : public BaseCRTP<Derived1> {
/*... should have an ordinary copy constructor... */
};
class Derived2 : public BaseCRTP<Derived2> {
/*... should have an ordinary copy constructor... */
};
You can then obviously implement the DeepCopy class in the usual way:
class DeepCopy
{
Base *basePtr;
public:
DeepCopy(const DeepCopy &dc)
: basePtr(dc.basePtr->clone())
{}
};
I think that templates are the best way to go in this situation:
template<typename Sub>
class DeepCopy
{
Base *base;
DeepCopy(Sub *sub)
{
base = new Sub(*sub); // use copy constructor
}
}
This does mean that DeepCopy's are un-assignable to each other, but that's the price you pay with C++.
How can I get derived class object from my generic interface pointer.
I do not want to type cast the generic interface in order to achieve above .
e.g:
class Base {}; // Has pure virtual functions and is my interface class
class Derived : public Base {}; // Additional functions .
Base *b = new Derived();
Now, I want to get derived pointer Derived *derived from b without casting.
How can I achieve this?
Your setup seems strange, I'd look for alternative options like returning Derived directly or moving the functions you need into base since you seem to need them.
If you still want to do that you could have something like:
class Derived; // Forward declaration
class Base {
public:
virtual Derived* as_derived() { return null; }
...
};
class Derived : public Base {
public:
Derived* as_derived() override { return this; }
};
Still, this looks like a hack and I would suggest casting instead. At least casting it's a common pattern and it will be easier for others to understand.
After writing a test, I determined that the this pointer in an interface is not equal to the this pointer of the concrete class, meaning I can't just use a C-style cast on it.
class AbstractBase {...};
class AnInterface {
public:
AnInterface() {...} // need AbstractBase * here
~virtual AnInterface() {...} // and here
};
class Concrete : public AbstractBase, public AnInterface {};
My interface needs a base class pointer to the concrete class inheriting it in the constructor and destructor in order to handle interface related registration and deregistration.
Every concrete object that inherits the interface needs to inherit the abstract base class first, it is always first in the layout.
For the constructor it is not all that hard, I can add a pointer in the interface constructor and pass this from the concrete class. But the destructor doesn't have any parameters, so I am in the dark there.
The solutions I came up with so far come with overhead:
1 - store the pointer in the interface to be used in the destructor - adds in one pointer worth of memory overhead
class AnInterface {
public:
AnInterface(AbstractBase * ap) {...}
~virtual AnInterface() {...} // and here
private:
AbstractBase * aPtr;
};
...
Concrete() : AnInterface(this) {}
2 - create an abstract method in the interface and implement it to return this in the concrete class - adds in the overhead of indirection for the virtual call
class AnInterface {
virtual AbstractBase * getPtr() = 0;
};
class Concrete : public AbstractBase, public AnInterface {
AbstractBase * getPtr() { return this; }
};
3 - dynamic_cast is even worse
Is there a more efficient way to achieve this?
IMO if decoupling between the base class and the interface is really needed, both solution 1 and 2 have tolerable overheads, certainly nothing that will be a problem on contemporary hardware.
But since you say that the interface is designed to work with the functionality, provided in the base class, then maybe the decoupling is not a good thing.
I mean if the problem is with inheriting multiple interfaces which all inherit the base class, or the "dreaded diamond" problem with inheritance, you can simply use virtual inheritance.
All of your concerns seem like micro-optimizations. Assuming you truly can't separate out your interface from your implementation (in which case, why are you using interfaces in the first place?) I would just use dynamic_cast and be done with it, even though it's pretty heavyweight. If I were stuck on a platform where RTTI isn't an option then I'd use option 2.
Your design has some flaws.
You should consider using CRTP as from the Mixin aspect, which saves you from keeping an extra pointer of the concrete derived.
template<typename Derived>
class AnInterface {
public:
AnInterface() {
Derived* derived = static_cast<Derived*>(this);
AbstractBase* abstractBase = static_cast<AbstractBase*>(derived);
} // have AbstractBase * here
~virtual AnInterface() {...} // and here
};
class Concrete
: public virtual AbstractBase
, public AnInterface<Concrete> {
AbstractBase * getPtr() { return this; }
};
I searched around and seems in order to perform this I need to change my Base class and want to know if this is the best approach.
For example,
I have a Base class:
class Base {}
Then a long line of derived classes:
class Derived_1:: public Base {}
class Derived_2:: public Derived_1{}
...
...
class Derived_n:: public Derived_M{}
And then I have another class:
class DeepCopy
{
Base * basePtr;
public:
DeepCopy(DeepCopy & dc) {}
}
Assuming the Base class and Derived_x class copy constructors are properly coded, what is the best way to write the copy constructor for DeepCopy. How can we know about the class that is in the basePtr of the object we are going to copy?
Only way I can think of is using RTTI, but using a long list of dynamic_casts seems not right. Besides it requires DeepCopy to know about the inheritance hierarchy of Base class.
The other method I saw is here. But it requires Base and Derived classes implement a clone method.
So is there a much easier, standard way of doing this?
You need to use the virtual copy pattern: provide a virtual function in the interface that does the copy and then implement it across the hierarchy:
struct base {
virtual ~base() {} // Remember to provide a virtual destructor
virtual base* clone() const = 0;
};
struct derived : base {
virtual derived* clone() const {
return new derived(*this);
}
};
Then the DeepCopy object just needs to call that function:
class DeepCopy
{
Base * basePtr;
public:
DeepCopy(DeepCopy const & dc) // This should be `const`
: basePtr( dc.basePtr->clone() )
{}
};
Using an approach that employs a clone() function is a good solution. Note using the CRTP (the curiously recurring template pattern) can save you some of the work. The way you do it is by introducing an intermediate level (called BaseCRTP below) which is a template and implements the clone() function. When you derive your actual classes, use them as the template argument of the base they are derived from. They will get the clone() function implemented for them automatically. Make sure the derived classes implement a copy constructor (or be sure the default is what you need).
/* Base class includes pure virtual clone function */
class Base {
public:
virtual ~Base() {}
virtual Base *clone() const = 0;
};
/* Intermediate class that implements CRTP. Use this
* as a base class for any derived class that you want
* to have a clone function.
*/
template <typename Derived>
class BaseCRTP : public Base {
public:
virtual Base *clone() const {
return new Derived(static_cast<Derived const&>(*this));
}
};
/* Derive further classes. Each of them must
* implement a correct copy constructor, because
* that is used by the clone() function automatically.
*/
class Derived1 : public BaseCRTP<Derived1> {
/*... should have an ordinary copy constructor... */
};
class Derived2 : public BaseCRTP<Derived2> {
/*... should have an ordinary copy constructor... */
};
You can then obviously implement the DeepCopy class in the usual way:
class DeepCopy
{
Base *basePtr;
public:
DeepCopy(const DeepCopy &dc)
: basePtr(dc.basePtr->clone())
{}
};
I think that templates are the best way to go in this situation:
template<typename Sub>
class DeepCopy
{
Base *base;
DeepCopy(Sub *sub)
{
base = new Sub(*sub); // use copy constructor
}
}
This does mean that DeepCopy's are un-assignable to each other, but that's the price you pay with C++.
I have been struggling with this kind of problem for a long time, so I decided to ask here.
class Base {
virtual ~Base();
};
class Derived1 : public Base { ... };
class Derived2 : public Base { ... };
...
// Copies the instance of derived class pointed by the *base pointer
Base* CreateCopy(Base* base);
The method should return a dynamically created copy, or at least store the object on stack in some data structure to avoid "returning address of a temporary" problem.
The naive approach to implement the above method would be using multiple typeids or dynamic_casts in a series of if-statements to check for each possible derived type and then use the new operator.
Is there any other, better approach?
P.S.: I know, that the this problem can be avoided using smart pointers, but I am interested in the minimalistic approach, without a bunch of libraries.
You add a virtual Base* clone() const = 0; in your base class and implement it appropriately in your Derived classes. If your Base is not abstract, you can of course call its copy-constructor, but that's a bit dangerous: If you forget to implement it in a derived class, you'll get (probably unwanted) slicing.
If you don't want to duplicate that code, you can use the CRTP idiom to implement the function via a template:
template <class Derived>
class DerivationHelper : public Base
{
public:
virtual Base* clone() const
{
return new Derived(static_cast<const Derived&>(*this)); // call the copy ctor.
}
};
class Derived1 : public DerivationHelper <Derived1> { ... };
class Derived2 : public DerivationHelper <Derived2> { ... };
An alternative is to have a pure virtual CreateCopy() method in the common base that is implemented in each derived class.