The following code tries to copy an object and keep the original type.
Unfortunately it does not work (every copied object will become a Super
instead of being of the same class as its original).
Please note that copySuper(const Super& givenSuper)
should not know anything about the subclasses of Super
.
Is it possible to do such a copy? Or do I have to change the definition of copySuper
?
#include <string>
#include <iostream>
class Super
{
public:
Super() {};
virtual ~Super() {};
virtual std::string toString() const
{
return "I'm Super!";
}
};
class Special : public Super
{
public:
Special() {};
virtual ~Special() {};
virtual std::string toString() const
{
return "I'm Special!";
}
};
Super* copySuper(const Super& givenSuper)
{
Super* superCopy( new Super(givenSuper) );
return superCopy;
}
int main()
{
Special special;
std::cout << special.toString() << std::endl;
std::cout << "---" << std::endl;
Super* specialCopy = copySuper(special);
std::cout << specialCopy->toString() << std::endl;
return 0;
}
//Desired Output:
// # I'm Special!
// # ---
// # I'm Special!
//
//Actual Output:
// # I'm Sepcial!
// # ---
// # I'm Super!
(There is a protected, not public, "clone" method inherited from Object.) The way to clone polymorphically is to obtain a copy from the superclass's clone() method, and then perform custom copying operations specific to this class.
A copy constructor can be called in various scenarios. For example: In the case where an object of a class is returned by value. In the case of an object of a class being passed, by value, to a function as an argument.
Passing by value (rather than by reference) means a copy needs to be made. So passing by value into your copy constructor means you need to make a copy before the copy constructor is invoked, but to make a copy you first need to call the copy constructor. Save this answer.
A copy constructor is a special type of constructor which initializes all the data members of the newly created object by copying the contents of an existing object. The compiler provides a default copy constructor.
Try this:
class Super
{
public:
Super();// regular ctor
Super(const Super& _rhs); // copy constructor
virtual Super* clone() const {return(new Super(*this));};
}; // eo class Super
class Special : public Super
{
public:
Special() : Super() {};
Special(const Special& _rhs) : Super(_rhs){};
virtual Special* clone() const {return(new Special(*this));};
}; // eo class Special
Note that we have implemented a clone() function that Special (and any other derivative of Super) overrides to create the correct copy.
e.g:
Super* s = new Super();
Super* s2 = s->clone(); // copy of s
Special* a = new Special();
Special* b = a->clone(); // copy of a
EDIT: As other commentator pointed out, *this
, not this
. That'll teach me to type quickly.
EDIT2: Another correction.
EDIT3: I really should not post so quickly when in the middle of work. Modified return-type of Special::clone() for covariant return-types.
This is what you need :
class Super
{
public:
Super()
{
}
virtual Super* clone() const
{
return( new Super(*this) );
};
};
class Special : public Super
{
public:
Special() : Super()
{
};
Special(const Special& _rhs) : Super(_rhs)
{
};
virtual Special* clone() const
{
return( new Special( *this ) );
};
};
int main()
{
Special a;
Super &c( a );
Super *b1 = c.clone();
Special *b2 = a.clone();
Super *b3 = a.clone();
}
One of previous examples has the clone for derived class wrong. The above is correct way of implementing the clone method.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With