#include <cstdio>
#include <memory>

class B {
private:
  virtual B *clone_impl( ){ return new B( *this ); }
protected:
  int b;
public:
  explicit B( int x ): b( x ){ }
  B( const B &that ): b( that.b ){ }
  virtual ~B( ){ }
  std::shared_ptr<B> clone( ){ return std::shared_ptr<B>( clone_impl( )); }
  virtual void print( ) const { std::printf( "B: %d\n", b ); };
};

class D: public B {
private:
  D *clone_impl( ) { return new D( *this ); }
protected:
  int d;
public:
  D( int x ): B(x), d( x*2 ){ }
  D( const D &that ): B( that.b ), d( that.d ){ }
  ~D( ){ }
  std::shared_ptr<D> clone( ){ return std::shared_ptr<D>( clone_impl( )); }
  void print( ) const { std::printf( "D: %d, %d\n", b, d ); };
};

int main(){
  B b(6);
  D d(42);

  b.print( );
  d.print( );

  B *bp = &d;
  bp->print( );

  std::shared_ptr<B> bfromb = b.clone( );
  std::shared_ptr<B> bfromd = d.clone( );
  std::shared_ptr<D> dfromd = d.clone( );
//  std::shared_ptr<D> dfromb = b.clone( ); // ERR
  std::shared_ptr<B> bfrombp = bp->clone( );
//  std::shared_ptr<D> dfrombp = bp->clone( ); // ERR

  bfromb->print( );
  bfromd->print( );
  dfromd->print( );
  bfrombp->print( );
}