I am trying to make a deep copy of the object d of class Derived as in the code below:
class A {
public:
int m_int;
A* clone() {
return new A(*this);
}
};
class Base {
public:
A* m_a;
virtual Base* clone() {
A* new_a = new A();
new_a = this->m_a->clone();
Base* clone = new Base(*this);
clone->m_a = new_a;
return clone;
}
};
class Derived : public Base {
public:
double m_dbl;
virtual Derived* clone() {
return new Derived(*this);
}
};
int main() {
Derived* d = new Derived();
d->m_dbl = 1.234;
A* a = new A();
a->m_int = -1;
d->m_a = a;
//clone d
Derived d_copy = d->clone();
//changing values of d's attributes must not affect d_copy
a->m_int = 10;
d->m_dbl = 3.456;
//check d_copy
cout << "m_int " << d_copy->m_a->m_int << endl;
cout << "m_dbl " << d_copy->m_dbl << endl;
}
output:
m_int 10 //wrong, should be -1;
m_dbl 1.234 //correct
As you can see, simply returning new Derived(*this) in Derived's clone() method is wrong since it does not deep-copy m_a.
If I "bring down" the deep-copying of m_a from Base to Derived then I will get the correct answer:
virtual Base* clone() = 0;
...
virtual Derived* clone() {
A* new_a = new A();
new_a = this->m_a->clone();
Derived* clone = new Derived(*this);
clone->m_a = new_a;
return new Derived(*this);
}
//gives out m_int = -1
If this is the case does this mean that each time I create further derived classes from Derived, I always have to "bring down" the contents of clone() to them?
Also, if for example Base has two derived classes Derived1 and Derived2, does this mean that I have to deep-copy the members of Base in each of them?
Any other ways to approach this?
You can consider of implementing the copy constructor that always is doing deep copy. In such case your clone implementation will always be trivial:
class Base {
public:
A* m_a;
Base(const A& other)
: m_a(other.m_a->clone())
{
}
virtual Base* clone() {
return new A(*this);
}
};
class Derived : public Base {
public:
double m_dbl;
Derived(const Derived& other)
: m_dbl(other.m_dbl)
virtual Derived* clone() {
return new Derived(*this);
}
};
If you don't want to change the behavior of the default constructor (you want the default constructor to make shallow copy for example) the alternative is to move copy implementation to a CopyTo method, so you can reuse it:
class Base {
public:
A* m_a;
static void CopyTo(const Base& from, Base& to)
{
to.m_a = from.m_a->clone();
}
virtual Base* clone() {
Base* result = new Base();
CopyTo(*this, result);
return result;
}
};
class Derived : public Base {
public:
double m_dbl;
static void CopyTo(const Base& from, Base& to)
{
Base::CopyTo(from, to);
to.m_dbl= from.m_dbl;
}
virtual Derived * clone() {
Derived * result = new Derived ();
CopyTo(*this, result);
return result;
}
virtual Derived* clone() {
return new Derived(*this);
}
};
Related
I have a Base class and a Derived class. Both have their own non-static data member and both have to have standard layout. So I can't inherit Derived from Base and have to declare then separately. I know I can define an operator Base& in the Derived class so that Base& base = derived works. Is there any way to make Base* pBase = pDerived works too (without an explicit cast)?
You can use a proxy object to represent a pointer:
struct Base;
struct Derived;
struct Ptr
{
Ptr(void* ptr) : ptr(ptr) { }
operator Base*() { return reinterpret_cast<Base*>(ptr); }
operator Derived*() { return reinterpret_cast<Derived*>(ptr); }
private:
void* ptr;
};
struct Base
{
Ptr operator&() { return Ptr(this); }
operator Derived&() { return *reinterpret_cast<Derived*>(this); }
};
struct Derived
{
Ptr operator&() { return Ptr(this); }
operator Base&() { return *reinterpret_cast<Base*>(this); }
};
void bar(Base*)
{ }
void foo()
{
Derived derived;
Base* base1 = &derived;
Base& base2 = derived;
bar(&derived);
}
This formal solution should be carefully analyzed for UB if used.
class Base {
public:
virtual Base* clone() const { return new Base(*this); }
// ...
};
class Derived: public Base {
public:
Derived* clone() const override { return new Derived(*this); }
// ...
};
int main() {
Derived *d = new Derived;
Base *b = d;
Derived *d2 = b->clone();
delete d;
delete d2;
}
i compile above code in the latest version of Xcode, and compiler complains
cannot initialize a variable of type "Derived*" with an rvalue of type "Base*"*
at Derived *d2 = b->clone().
But I already make clone virtual and let the clone() in Derived return Derived *.
Why do I still have such problem?
The return type of Base::clone() is Base*, not Derived*. Since you are invoking clone() through a Base*, the expected return value is a Base*.
If you invoke clone() through a Derived*, you will be able to use the return type of Derived::clone().
Derived *d = new Derived;
Derived *d2 = d->clone(); // OK
Also,
Base *b = d;
Derived *d2 = dynamic_cast<Derived*>(b->clone()); // OK
Also,
Base *b = d;
Derived *d2 = dynamic_cast<Derived*>(b)->clone(); // OK
I have a class which uses a class of base pointers to derived objects, so I need to have my own desructor for deleting the vector's elements and custom copy and assignment funcitons. I'm not entirely sure about the preferred way of implementing a structure like below and writing the right copy and assignment constructors and destructors for it. May I ask you to guide me? I've read a lot and searched but I'm still not sure.
class Base
{
public:
Base();
~virtual Base();
int a;
int type; // Derived1 or Derived2
std::string b;
...
}
class Derived1 : public Base
{
public:
Derived1();
Derived1(const Base* a);
virtual ~Derived1();
}
class Derived1
{
Derived1::Derived1(const Base *a) : Base(a)
{
}
}
class Derived2 : public Base
{
public:
Derived2();
Derived2(const Base* a);
virtual ~Derived2();
std::string d1;
std::string d2;
int d3;
}
class Derived2
{
Derived2::Derived2(const Base *a) : Base(a) {
this->d1 = ((Derived2*)a)->d1;
this->d2 = ((Derived2*)a)->d2;
this->d3 = ((Derived2*)a)->d3;
}
}
class A
{
public:
A();
~A();
A(const A& a);
A& operator = (const A& a);
std::string someString;
std::vector<Base*> vect;
}
A::~A() {
std::vector<Base*>::iterator it = vect.begin();
while (it != vect.end()) {
delete (*it);
it++;
}
A::A(const A &a)
{
someString = a.someString;
for(std::size_t i = 0; i < a.vect.size(); ++i {
someString = a.someString;
Base* base = a.vect.at(i);
if(base->type == base::TypeD1) {
base = new Derived1( a.vect.at(i) );
vect.push_back( base );
}
else {
base = new Derived2( a.vect.at(i) );
vect.push_back( base );
}
}
}
Your loop in the destructor is fine in practice, and is the
usual solution. Formally, it is undefined behavior, since you
are leaving objects in the vector (pointers to deleted objects)
which aren't copiable, but in practice: the vector won't copy
them unless you resize it to something bigger, or insert or
erase on it. If you really want to avoid the undefined
behavior:
for ( auto current = vect.begin(); current != vect.end(); ++ current ) {
Base* tmp = *it;
*it = nullptr;
delete tmp;
}
But this is one case where I probably wouldn't bother (and
I tend to be more sensitive to undefined behavior than most).
First, do you actually need to copy and assign objects of type A? If no, the simple solution is:
class A
{
public:
A();
~A();
A(const A&) = delete;
A(A&&) = default;
A& operator=(const A&) = delete;
A& operator=(A&&) = default;
// ...
};
If yes, then you want some polymorphic way of copying the elements of the vector. (Any time at all you have if (b->type == Base::TypeD1) { do_this(); } else { do_that(); }, stop and think if it would make sense to add a virtual function for do_this/do_that. The else-if-heimer's way doesn't allow for future new derived classes; the virtual way does.)
class Base
{
public:
// ...
virtual Base* clone() const = 0;
// ...
};
class Derived1 : public Base
{
public:
virtual Derived1* clone() const;
};
Derived1* Derived1::clone() const {
return new Derived1(*this);
}
The copy assignment operator of A will need to destroy the old contents of the lhs, just like the destructor, and then copy the new contents over, just like the copy constructor. So let's put those two operations in private functions:
class A
{
public:
A();
~A();
A(const A&);
A(A&&) = default;
A& operator=(const A&);
A& operator=(A&&) = default;
// ...
private:
void destroy_contents();
void copy_from(const std::vector<Base*>& v);
};
void A::destroy_contents() {
std::vector<Base*>::iterator it = vect.begin();
while (it != vect.end()) {
delete (*it);
++it;
}
vect.clear();
}
void A::copy_from(const std::vector<Base*>& v) {
std::vector<Base*>::const_iterator it = v.begin();
while (it != v.end()) {
vect.push_back((*v)->clone());
++it;
}
}
A::~A() { destroy_contents(); }
A::A(const A& a) :
someString(a.someString),
vect()
{
copy_from(a.vect);
}
A& A::operator=(const A& a) {
if (this != &a) {
someString = a.someString;
destroy_contents();
copy_from(a.vect);
}
return *this;
}
If you have a vector of any pointer type, the vector does not know anything about the type behind the pointer, nor does it care: The vector operates on the pointers only, copying them to a new location if need be, but never even touching the objects themselves. As such, it is your responsibility to destroy the objects themselves.
As James Kanze points out, there is a slight danger of undefined behavior when handling invalidated pointers. However, since the vector is not used in any way after deleting the objects it holds, no undefined behavior is invoked in the code you've given (the vector won't need to reallocate its memory so it won't need to assign invalidated pointers, and destruction of pointers is a noop). As such, your destructor of class A is perfectly fine.
The copy constructor of class A, however, is unnecessarily complicated and an ample source of errors (it needs to be updated whenever a new derived class is defined!). The best way to do this is to use a clone() function:
class Base {
public:
//...
virtual Base* clone() const = 0; //Returns a new copy of the object. Pure virtual if the Base class is abstract.
};
class Derived1 : public Base {
public:
Derived1(const Derived& a);
virtual Derived* clone() const {
return new Derived1(*this);
}
};
If you make clone() pure virtual in the base class, you have the guarantee that your compiler will complain if you forget to implement it in any derived class. With that, the copy constructor of class A is next to trivial:
A::A(const A &a) {
someString = a.someString;
for(std::size_t i = 0; i < a.vect.size(); ++i {
vect.push_back(a.vect[i]->clone());
}
}
So I'm having a little bit of problems understanding how I should fix this polymorphic issue I've ran into. To make things short, let's define only two levels of classes, a father and two sons:
The parent:
class Entity {
public:
int x;
Entity();
~Entity();
Entity(const Entity&);
Entity &operator=(const Entity&);
};
The two sons:
class EntitySon1 : public Entity {
public:
int b;
EntitySon1();
~EntitySon1();
EntitySon1(const EntitySon1&);
EntitySon1 &operator=(const EntitySon1&);
};
class EntitySon2 : public Entity {
public:
int a;
EntitySon2();
~EntitySon2();
EntitySon2(const EntitySon2&);
EntitySon2 &operator=(const EntitySon2&);
};
Please, forget the fact that in this example all classes only have an int value and the standard operator= should therefore be enough, in the real project these classes are more complex so I do have the need to implement one myself and they are succesfully calling parent ones as well.
So now, somewhere in my project, I have an array of Entity*, which can only be either son1 or son2. I want to go through this array of entities and make copies into another array. The code I'd like to be able to write is something like:
for (i = 0; i < entities; ++i) {
entityCopiesArray[i] = entitiesArray[i];
}
Problem is, both entityCopiesArray and entitiesArray are of type (Entity*) so when the assign is done, only Entity.operator=() gets called, while I need, in the case that current Entity is son1, have both Entity.operator=() and EntitySon1.operator=() called.
I know I can cast each variable on the array so the right operator gets called, but that needs extra information to tell which entities are son1, which are son2, and also need to be typed manually for every possible Entity's son.
Is there any other way around this, or am I stuck with doing:
if (isSon1())
(EntitySon1)entityCopiesArray[i] = (EntitySon1)entitiesArray[i];
else if (isSon2())
(EntitySon2)entityCopiesArray[i] = (EntitySon2)entitiesArray[i];
// ... etc
edit: I made this post late night and tried to compact the information as much as possible so I said things that weren't accurate. I obviously have an array to Entity*, else I wouldn't be able to use polymorphism.
Consider the following:
struct Base {
int a;
};
struct Derived1 : public Base {
int d1Data[100];
};
struct Derived2 : public Base {
char d2Data[1500];
};
Now if we do the following:
Entity* e = new Entity;
Derived1* d1 = new Derived1;
Derived2* d2 = new Derived2;
std::cout << sizeof(*e) << ", " << sizeof(*d1) << ", " << sizeof(*d2) << '\n';
What will the output be? Hint: The numbers are not going to be the same.
So now what happens in each of the following cases?
*e = *(Entity*)d1;
*(Derived1*)e = *d1;
*(Derived2*)d1 = *d2;
*(Entity*)d1 = *(Entity*)(d2);
*(Derived1*)d2 = *d1;
None of these cases is particularly good. Your post makes it sound like you are setting yourself up for a bad case of object slicing.
DO NOT DO.
On the other hand, if what you are looking to do is to clone objects from a list:
std::vector<Base*> entities;
std::vector<Base*> copies;
entities.push_back(new Derived1);
entities.push_Back(new Derived2);
for (size_t i = 0; i < entities.size(); ++i) {
Base* clone = make_a_copy_of(entities[i]);
}
then the way to do this is to add a member function to Base.
struct Base {
int a;
virtual Base* clone() const = 0;
};
struct Derived1 : public Base {
int d1Data[100];
Base* clone() const override {
return new Derived1(*this);
}
};
struct Derived2 : public Base {
char d2Data[1500];
Base* clone() const override {
return new Derived2(*this);
}
};
int main() {
std::vector<Base*> entities;
std::vector<Base*> copies;
entities.push_back(new Derived1);
entities.push_Back(new Derived2);
for (size_t i = 0; i < entities.size(); ++i) {
Base* clone = entities[i]->clone();
}
// remember to delete all the objects we allocated,
// or wrap them with std::unique_ptr
return 0;
}
I will probably be scowled at for using raw pointers like this without using something like std::unique_ptr to ensure the objects have a lifetime, so here is a complete version using unique_ptr. I'm not using make_unique because neither my GCC (4.8.2) or MSVC appear to support it.
#include <iostream>
#include <vector>
#include <memory>
struct Base {
int m_a;
Base(int a) : m_a(a) {}
virtual ~Base() { std::cout << "Dtoring " << m_a << '\n'; }
virtual std::unique_ptr<Base> clone() const = 0;
};
struct Derived1 : public Base {
int d1Data[100];
Derived1(int a) : Base(a) {}
virtual ~Derived1() { std::cout << "D1 at " << (void*)this << " dtord\n"; }
std::unique_ptr<Base> clone() const override { return std::unique_ptr<Derived1>(new Derived1 (*this)); }
};
struct Derived2 : public Base {
char d2Data[10000];
Derived2(int a) : Base(a) {}
virtual ~Derived2() { std::cout << "D1 at " << (void*)this << " dtord\n"; }
std::unique_ptr<Base> clone() const override { return std::unique_ptr<Derived2>(new Derived2 (*this)); }
};
int main()
{
std::vector<std::unique_ptr<Base>> entities;
{
std::vector<std::unique_ptr<Base>> copies;
entities.emplace_back(new Derived1 (3));
entities.emplace_back(new Derived2 (5));
for (auto& ent : entities) {
copies.emplace_back(ent->clone());
}
std::cout << "copies going out of scope\n";
}
std::cout << "entities going out of scope\n";
return 0;
}
Live demo: http://ideone.com/lrgJun
---- EDIT ----
When you inherit a class, you also inherit it's data members into your overall structure. In this example, the effective structure of Derived1 is:
struct Derived1 {
int a; // from Base
int d1Data[100];
};
My implementation of clone is quietly relying on the copy constructor which is essentially doing a memory copy of src to dest, the equivalent of memcpy(this, src, sizeof(*this));. Because of this you don't need to chain calls to clone or anything like that, the magic is done in the copy constructor.
If you need to add instances of Base into your mix, we can implement the clone member in Base - but bear in mind that any "special" members you add to Base are going to be inherited in all the derived classes too.
I'll convolute the classes a little and show you what the copy constructors for Base and Derived1 effectively look like:
struct Base {
int m_int;
double m_double;
std::string m_name;
private:
unsigned int m_baseOnly;
...
};
struct Derived1 : public Base {
// inherited m_int, m_double and m_name
// also inherited m_baseOnly, we just can't access it.
std::array<int, 100> m_data;
std::string m_title;
std::shared_ptr<Base> m_buddy;
...
};
At this point, the actual in-memory structure of a Derived1 looks like this:
Derived1 {
int m_int;
double m_double;
std::string m_name;
unsigned int m_baseOnly;
std::array<int, 100> m_data;
std::string m_title;
std::shared_ptr<Base> m_buddy;
};
Given these definitions, unless we implement our own copy constructor or disable copy construction, this is effectively what the compiler will generate for us:
Base::Base(const Base& rhs) // Base copy constructor
: m_int(rhs.m_int)
, m_double(rhs.m_double)
, m_name(rhs.m_name)
, m_baseOnly(rhs.m_baseOnly)
{
}
Derived1::Derived1(const Derived1& rhs)
: Base(rhs) // copy-construct the Base portion
, m_data(rhs.m_data) // hence why I used std::array
, m_title(rhs.m_title)
, m_buddy(rhs.m_buddy)
{
}
My implementation of clone for Derived1
std::unique_ptr<Base> clone() const override
{
return std::unique_ptr<Derived1>(new Derived1 (*this));
}
or
std::unique_ptr<Base> clone() const override
{
const Derived1& rhs = *this; // Reference to current object.
Derived1* newClone = new Derived1(rhs);
return std::unique_ptr<Derived1>(newClone);
}
which is creating a new Derived1, invoking the new, empty, clone's copy-ctor with the current object as rhs and filling out the clone.
I have an array of Entities, which can only be either son1 or son2.
In general this is not possible. But you can have an array of Entity*, each of which points to a Son1 or a Son2. Then you can have a virtual clone function such that a member of this family creates a copy of itself and returns a pointer (of type Entity*) to it. Then you can copy the array quite easily.
let's say I have a pointer to some base class and I want to create a new instance of this object's derived class. How can I do this?
class Base
{
// virtual
};
class Derived : Base
{
// ...
};
void someFunction(Base *b)
{
Base *newInstance = new Derived(); // but here I don't know how I can get the Derived class type from *b
}
void test()
{
Derived *d = new Derived();
someFunction(d);
}
Cloning
struct Base {
virtual Base* clone() { return new Base(*this); }
};
struct Derived : Base {
virtual Base* clone() { return new Derived(*this); }
};
void someFunction(Base* b) {
Base* newInstance = b->clone();
}
int main() {
Derived* d = new Derived();
someFunction(d);
}
This is a pretty typical pattern.
Creating new objects
struct Base {
virtual Base* create_blank() { return new Base; }
};
struct Derived : Base {
virtual Base* create_blank() { return new Derived; }
};
void someFunction(Base* b) {
Base* newInstance = b->create_blank();
}
int main() {
Derived* d = new Derived();
someFunction(d);
}
Though I don't think that this a typical thing to do; it looks to me like a bit of a code smell. Are you sure that you need it?
It's called clone and you implement a virtual function that returns a pointer to a dynamically-allocated copy of the object.