Virtual Ctor Idiom and auto_ptr
In the FAQ, the virtual constructor idioms, create() and clone(), use raw
pointer return values.
Wouldn't it be better if these returned auto_ptr's instead?
But then covariant return types can't be exploited.
Here's some sample code.
Note that the use of clone() in main() is difficult to upcast.
I suppose that if one is using clone() then polymorphic behavior is probably
desired, so the upcast typically isn't necessary.
terry
#include <iostream>
#include <memory>
#include <cassert>
#include <typeinfo>
class Base {
private:
int aBaseMember;
public:
std::auto_ptr<Base> create() const {
Base* ptr = doCreate();
assert(typeid(*ptr) == typeid(*this));
return std::auto_ptr<Base>(ptr);
} // create
std::auto_ptr<Base> clone() const {
Base* ptr = doClone();
assert(typeid(*ptr) == typeid(*this));
return std::auto_ptr<Base>(ptr);
} // clone
void print(std::ostream& os) const { doPrint(os); }
virtual ~Base() { }
protected:
Base() : aBaseMember(0) { }
Base(const Base& other) { aBaseMember = other.aBaseMember; }
private:
virtual Base* doCreate() const = 0;
virtual Base* doClone() const = 0;
protected:
virtual void doPrint(std::ostream& os) const = 0;
}; // Base
inline
void Base::doPrint(std::ostream& os) const
{ os << "Base(" << aBaseMember << ")"; }
inline std::ostream& operator<<(std::ostream& os, const Base& base) {
base.print(os);
return os;
} // << Base
class Derived: public Base {
private:
int aDerivedMember;
public:
Derived()
: Base()
, aDerivedMember(0)
{ }
Derived(const Derived& other)
: Base(other)
{ aDerivedMember = other.aDerivedMember; }
private:
Derived* doCreate() const { return new Derived(); }
Derived* doClone() const { return new Derived(*this); }
void doPrint(std::ostream& os) const {
os << "Derived(" << aDerivedMember <<"): ";
Base::doPrint(os);
} // doPrint
}; // Derived
int main() {
Derived x;
std::cout << "x=" << x << std::endl;
std::auto_ptr<Base> b = x.clone(); // Easy to use polymorphically.
std::cout << "b=" << *b << std::endl;
// Icky. Is there a better way?
std::auto_ptr<Derived> d(dynamic_cast<Derived*>(x.clone().release()));
std::cout << "d=" << *d << std::endl;
} // main
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]