// Remove "x" to invoke feature.
#define xTEST_ABSTRACT_CLONE
#if defined( CPP11 )
# define OVERRIDE override
# define IS_DELETED = delete
# include <memory>
template< class Type >
struct Ownership { using Ptr = std::unique_ptr<Type>; };
#else
# define OVERRIDE
# define IS_DELETED
# include <memory> // Note: std::auto_ptr is deprecated.
template< class Type >
struct Ownership { typedef std::auto_ptr<Type> Ptr; };
#endif
//---------------------------------------------------------------------------
#include <assert.h> // assert
#include <iostream> // std::wcout, std::wcerr, std::endl
#include <memory> // std::unique_ptr
#include <string> // std::string
#include <typeinfo> // std::typeinfo, i.e. typeid usage.
using namespace std;
class Person
{
private:
string name_;
Person& operator=( Person const& ) IS_DELETED;
virtual Person* virtualClone() const
{
assert( typeid( *this ) == typeid( Person ) );
return new Person( *this );
}
public:
string name() const { return name_; }
Ownership<Person>::Ptr clone() const
{
return Ownership<Person>::Ptr( virtualClone() );
}
Person( string const& name )
: name_( name )
{}
};
class Student
: public Person
{
private:
int studentId_;
Student& operator=( Student const& ) IS_DELETED;
virtual Student* virtualClone() const OVERRIDE
{
assert( typeid( *this ) == typeid( Student ) );
return new Student( *this );
}
public:
int studentId() const { return studentId_; }
Ownership<Person>::Ptr clone() const
{
return Ownership<Person>::Ptr( virtualClone() );
}
Student( string const& name, int const studentId )
: Person( name ), studentId_( studentId )
{}
};
wostream& operator<<( wostream& stream, string const& s )
{
return (stream << s.c_str());
}
int main()
{
Person a( "Hillary Clinton" );
Student b1( "John Smith", 12345 );
Student b2( "Mary Jones", 88888 );
Person& bAsPerson = b1; // OK.
Ownership<Person>::Ptr pClone;
wcout
<< "Name: " << b1.name()
<< ". Student id: " << b1.studentId() << "."
<< endl;
#ifdef TEST_ABSTRACT_CLONE
pClone = bAsPerson.clone(); // OK, clones John Smith the Student.
#else
pClone = b2.clone(); // More obviously (?) OK, clones Mary.
#endif
Student& studentRef = dynamic_cast<Student&>( *pClone );
wcout
<< "Name: " << studentRef.name()
<< ". Student id: " << studentRef.studentId() << "."
<< endl;
}