As Scott Myers wrote, you can take advantage of a relaxation in C++'s type-system to declare clone() to return a pointer to the actual type being declared:
class Base
{
virtual Base* clone() const = 0;
};
class Derived : public Base
{
virtual Derived* clone() const
};
The compiler detects that clone() returns an pointer to the type of the object, and allows Derived to override it to return a pointer to derived.
It would desirable to have clone() return a smart pointer that implies transfer of ownership semantics, like the following:
class Base
{
virtual std::auto_ptr<Base> clone() const = 0;
};
class Derived : public Base
{
virtual std::auto_ptr<Derived> clone() const;
};
Unfortunately, the relaxation of the conventions does not apply to templated smart pointers, and the compiler will not allow the override.
So, it seems I am left with two options:
Is one of these approaches preferred? Or is there a way for me to eat my transfer of ownership semantics and have my strong type safety too?
C++ Reference. Programming Terms. Function Signatures. A function signature consists of the function prototype. What it tells you is the general information about a function, its name, parameters, what scope it is in, and other miscellaneous information.
In C++, a Copy Constructor may be called for the following cases: 1) When an object of the class is returned by value. 2) When an object of the class is passed (to a function) by value as an argument. 3) When an object is constructed based on another object of the same class.
A copy constructor defines what copying means,So if we pass an object only (we will be passing the copy of that object) but to create the copy we will need a copy constructor, Hence it leads to infinite recursion. So, A copy constructor must have a reference as an argument.
No you can't, constructors can't be virtual.
Use the Public non-virtual / Private virtual pattern :
class Base {
public:
std::auto_ptr<Base> clone () { return doClone(); }
private:
virtual Base* doClone() { return new (*this); }
};
class Derived : public Base {
public:
std::auto_ptr<Derived> clone () { return doClone(); }
private:
virtual Derived* doClone() { return new (*this); }
};
The syntax isn't quite as nice, but if you add this to your code above, doesn't it solve all your problems?
template <typename T>
std::auto_ptr<T> clone(T const* t)
{
return t->clone();
}
I think the function semantics are so clear in this case that there is little space for confusion. So I think you can use the covariant version (the one returning a dumb pointer to the real type) with an easy conscience, and your callers will know that they are getting a new object whose property is transferred to them.
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