fork download
  1. // Remove "x" to invoke feature.
  2. #define xTEST_ABSTRACT_CLONE
  3.  
  4. #if defined( CPP11 )
  5. # define OVERRIDE override
  6. # define IS_DELETED = delete
  7. # include <memory>
  8. template< class Type >
  9. struct Ownership { using Ptr = std::unique_ptr<Type>; };
  10. #else
  11. # define OVERRIDE
  12. # define IS_DELETED
  13. # include <memory> // Note: std::auto_ptr is deprecated.
  14. template< class Type >
  15. struct Ownership { typedef std::auto_ptr<Type> Ptr; };
  16. #endif
  17.  
  18. //---------------------------------------------------------------------------
  19. #include <assert.h> // assert
  20. #include <iostream> // std::wcout, std::wcerr, std::endl
  21. #include <memory> // std::unique_ptr
  22. #include <string> // std::string
  23. #include <typeinfo> // std::typeinfo, i.e. typeid usage.
  24. using namespace std;
  25.  
  26. class Person
  27. {
  28. private:
  29. string name_;
  30.  
  31. Person& operator=( Person const& ) IS_DELETED;
  32.  
  33. virtual Person* virtualClone() const
  34. {
  35. assert( typeid( *this ) == typeid( Person ) );
  36. return new Person( *this );
  37. }
  38.  
  39. public:
  40. string name() const { return name_; }
  41.  
  42. Ownership<Person>::Ptr clone() const
  43. {
  44. return Ownership<Person>::Ptr( virtualClone() );
  45. }
  46.  
  47. Person( string const& name )
  48. : name_( name )
  49. {}
  50. };
  51.  
  52. class Student
  53. : public Person
  54. {
  55. private:
  56. int studentId_;
  57.  
  58. Student& operator=( Student const& ) IS_DELETED;
  59.  
  60. virtual Student* virtualClone() const OVERRIDE
  61. {
  62. assert( typeid( *this ) == typeid( Student ) );
  63. return new Student( *this );
  64. }
  65.  
  66. public:
  67. int studentId() const { return studentId_; }
  68.  
  69. Ownership<Person>::Ptr clone() const
  70. {
  71. return Ownership<Person>::Ptr( virtualClone() );
  72. }
  73.  
  74. Student( string const& name, int const studentId )
  75. : Person( name ), studentId_( studentId )
  76. {}
  77. };
  78.  
  79. wostream& operator<<( wostream& stream, string const& s )
  80. {
  81. return (stream << s.c_str());
  82. }
  83.  
  84. int main()
  85. {
  86. Person a( "Hillary Clinton" );
  87. Student b1( "John Smith", 12345 );
  88. Student b2( "Mary Jones", 88888 );
  89. Person& bAsPerson = b1; // OK.
  90. Ownership<Person>::Ptr pClone;
  91.  
  92. wcout
  93. << "Name: " << b1.name()
  94. << ". Student id: " << b1.studentId() << "."
  95. << endl;
  96.  
  97. #ifdef TEST_ABSTRACT_CLONE
  98. pClone = bAsPerson.clone(); // OK, clones John Smith the Student.
  99. #else
  100. pClone = b2.clone(); // More obviously (?) OK, clones Mary.
  101. #endif
  102. Student& studentRef = dynamic_cast<Student&>( *pClone );
  103.  
  104. wcout
  105. << "Name: " << studentRef.name()
  106. << ". Student id: " << studentRef.studentId() << "."
  107. << endl;
  108. }
  109.  
Success #stdin #stdout 0.01s 2876KB
stdin
Standard input is empty
stdout
Name: John Smith. Student id: 12345.
Name: Mary Jones. Student id: 88888.