I'm trying to make a copy of a derived class with only a base class pointer.
So if I have:
class BaseClass; //Abstract class with =0 functions
class LeftClass : BaseClass;
class RightClass : BaseClass;
And I have a function that takes a BaseClass as a parameter:
void Function(BaseClass* baseClass)
I want to make a copy of BaseClass, but I want to also copy the extended functionality of LeftClass OR RightClass, but I don't know which one was passed to the function - both are possible.
So I have something like this:
//global
vector<BaseClass*> myVector;
void Function(BaseClass* baseClass)
{
BaseClass* baseClassCopy = new BaseClass(baseClass);
myVector.push_back(baseClassCopy);
}
And then I call the function with a left or right class
int main()
{
LeftClass leftClass;
Function(&leftClass);
LeftClass* ResultOfCopy = myVector.at(0);
}
That code doesn't copy over the entire leftclass as a copy, is there a way to do this I'm overlooking?
Also BaseClass is abstract, some of the functions are =0 so I can't new one up. Otherwise there is a copy function in the other classes to use.
If you can't change any of the classes to add a clone function then you can manually do that yourself by using dynamic_cast to determine its run time type and call the correct derived constructor. That would look like
void Function(BaseClass* baseClass)
{
if (auto ptr = dynamic_cast<LeftClass*>(baseClass))
myVector.push_back(new LeftClass(*ptr));
if (auto ptr = dynamic_cast<RightClass*>(baseClass))
myVector.push_back(new RightClass(*ptr));
}
and you can see it working in this live example
This kind of problem is usually solved by a clone() method.
class BaseClass
{
virtual BaseClass* clone() = 0
};
class LeftClass: public BaseClass
{
virtual LeftClass* clone() override {return new LeftClass(*this);}
};
class RightClass: public BaseClass
{
virtual RightClass* clone() override {return new RightClass(*this);}
};
class RightRightClass: public RightClass
{
virtual RightRightClass* clone() override {return new RightRightClass(*this);}
};
Your function is now easy to write:
void Function(BaseClass* baseClass)
{
BaseClass* baseClassCopy = !baseClass ? nullptr : baseClass->clone();
myVector.push_back(baseClassCopy);
}
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++.
Suppose we want to implement strategy pattern. We have an interface Base and two derived classes -- A and B. Instances of Doer class can choose between A's and B's methods do(). And the question is how to complete the code to make how it should be.
class Base {
virtual void do() const = 0;
};
class A: public Base {
void do() const override {};
};
class B: public Base {
void do() const override {};
}
class Doer {
public:
Doer(std::unique_ptr<Base> b_ptr) : ptr(b_ptr) {}
void do() const { ptr->do(); }
private:
std::unique_ptr<Base> ptr;
}
int main() {
Doer doer(std::unique_ptr<Base>());
doer.do();
return 0;
}
Doer doer(std::make_unique<A>()); // or std::make_unique<B>()
The above is pretty much it. std::unique_ptr works very hard to implement the same coercion as the raw pointer it holds.
There are three major problems with your code.
1) do is a keyword of the language. You cannot use it as an identifier (like function name)
2) you take b_ptr by value, so you need to move from it:
Doer(std::unique_ptr<Base> b_ptr) : ptr(std::move(b_ptr)) {}
3) you pass an empty unique_ptr to Doer's constructor, which is equivalent to passing a nullptr. You also try to instantiate the base class. It is impossible because Base is a pure virtual class. Use make_unique with a derived type:
Doer doer(std::make_unique<A>());
How would I do so without making base method virtual?
class Base {
public:
bool foo() const;
}
class Derived : public Base{
public:
bool foo() const;
}
There is no any sense to call isEmpty of a derived class from isEmpty of the base class because the base class knows nothing about its derived classes. Take into account that the base class is single while there can be numerous derived classes. So of what derived class are you going to call function isEmpty?
There is sense to call isEmpty of the base class in a derived class. it can be done the following way
bool Derived::isEmpty() const
{
return Base::isEmpty();
}
You cannot. That's why there is a virtual keyword. If your class forbids use of this keyword, I'd rather not use it as a starting point to learn OOP.
If you really need this, you can store a null pointer to a function with the foo's signature in your base class instances, and use the base implementation until this pointer is null. Then you can change this pointer in your derived class and associate is with your derived implementation. Then your base class can call that function via the pointer.
Below is some schematic code for this:
class Base {
public:
bool foo() const {
if (NULL == internalFoo) {
// base implementation;
} else {
return internalFoo();
}
}
private:
bool (*internalFoo)() = NULL;
}
class Derived : public Base{
public:
bool foo() const;
}
I want to copy objects in c++. The problem is that i have derived classes with polymorphism, as shown i the pseudocode below:
class BaseCl { some virtual functions };
class DerivedClass : public BaseCl { ... };
...
BaseCl * b1 = new DerivedClass();
BaseCl * b2 = new "copy of b1"; (just pseudocode)
The problem is the last line:
I want to copy an object of the class "BaseCl", but because of the polymorphism the copy must be just like the original object of "DerivedClass".
What is the best way to do that?
Thank you very much, any help is appreciated.
Edit: Problem has been solved:
Inserted:
virtual BaseCl *clone() = 0;
in the base class and
DerivedCl *clone() {return new DerivedCl(*this);}
in the derived class. Thank you all.
You need to define a function in BaseC1 that makes a clone. Something like:
class BaseCl
{
virtual BaseCl* clone() {return new BaseC1(*this);}
};
class DerivedClass : public BaseCl
{
virtual BaseCl* clone() {return new DerivedClass(*this);}
};
The key of runtime polymorphism is that operations must be implemented in the most derived object, since it is the one than know everything it has to be known to perform them. All bases must expose virtual functions to be called by base pointers.
You can devine at the base level a virtual BaseCl* clone() function, and override it your derived classes to return new DerivedClass(*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++.