Copy constructor / assignment with abstract classes

Started by
4 comments, last by MaulingMonkey 19 years, 6 months ago
Hi, Let's say I have this code:

// B is purely an abstract interface
class B { /* details */ };

class D1 : public B { /* details */ };
class D2 : public B { /* details */ };

class Main
{
  private:
    B* b_;

  public:
// Ctor and dtor
    Main() : b_(new D1) {}
    dMain() {delete b_;} // Destructor - alt 126 doesn't work here!

// Change data
    void ChangeToD1() {delete b_; b_ = new D1;}
    void ChangeToD2() {delete b_; b_ = new D2;}

// Copy assignment and constructor
    Main(const Main& rhs);
    Main& operator=(const Main& rhs);
};


So the main class contains a pointer to B, which can take the form of either D1 or D2. However, how do you then write the copy ctor and copy assignment code? How do you know what 'new' to call for b_? Is it just a memcpy call? Thanks in advance for any help, Jim.
Advertisement
Copy ctor's in such classes should probably be private.

The typical method is to add a virtual method called Clone to accomplish this (look-up something called co-variant return types).

Er wait, is this Java or C++ code?
- The trade-off between price and quality does not exist in Japan. Rather, the idea that high quality brings on cost reduction is widely accepted.-- Tajima & Matsubara
Quote:Original post by Magmai Kai Holmlor
The typical method is to add a virtual method called Clone to accomplish this (look-up something called co-variant return types).


EDITED (multiple times) Example:

class B{public:    virtual B * clone ( void ) const = 0;    virtual B * create( void ) const = 0;    virtual ~B() {}};class D1 : public B{public:    virtual D1 * clone ( void ) const { return new D1(*this); }    virtual D1 * create( void ) const { return new D1; }};class D2 : public B{public:    virtual D2 * clone ( void ) const { return new D2(*this); }    virtual D2 * create( void ) const { return new D2; }};


Quote:Er wait, is this Java or C++ code?


Java has C++ style pointers now? ----> B* b_;

;-)

[Edited by - MaulingMonkey on October 16, 2004 10:20:05 PM]
virtual constructor idiom

Quote:Original post by MaulingMonkey
Quote:Original post by Magmai Kai Holmlor
The typical method is to add a virtual method called Clone to accomplish this (look-up something called co-variant return types).


Example:


Don't wont to be a pain in the butt but there syntax errors in that code:

struct B {    virtual B* clone() const = 0;    virtual B* create() const = 0;    virtual ~B() {};};struct D1 : B {   /* ... */      D1(const D1&); //need a copy constructor for clone, either implicitly or explicitly defined      B* create() const { return new D1; }   B* clone() const { return new D1(*this); }};struct D2 : B {  /* ... */  D2(const D2&); //need a copy constructor for clone, either implicitly or explicitly defined  B* create() const { return new D2; }  B* clone() const { return new D2(*this); }};
Thanks very much - that's really kind of elegant!

The only other comment (for anyone who browses this but misses the link) is on the return types of the clone and create functions - according to the link recent compilers should use D1* clone() instead of B* clone() (where appropriate of course).

Ratings++ all around.
Quote:Original post by snk_kid
Don't wont to be a pain in the butt but there syntax errors in that code


That's not being a pain in the butt, that's underscoring the point that I really shouldn't be posting at like, 5am without any sleep ^_^.

Quote:Original post by JimPrice
The only other comment (for anyone who browses this but misses the link) is on the return types of the clone and create functions - according to the link recent compilers should use D1* clone() instead of B* clone() (where appropriate of course).


I'm guessing that's because you shouldn't be able to do this without covariant return types:

D1 * somepointer = ...; //we know this has to be a D1 or derivedD1 * aclone = somepointer->clone(); //this wouldn't compile so well with B* return types


And using this form wouldn't work so well if somepointer pointed to a derived class of D1:

D1 * somepointer = ...;D1 * aclone = new D1(*somepointer);


The workaround on older compilers would be:

D1 * somepointer = ...;D1 * aclone = static_cast<D1 *>(somepointer->clone());


But I like these covariants... interesting... *is inaugurated to understanding the reason behind covariants for the first time due to his brain fart*

edit: I should note, GCC 3.3.1 officially counts as a newer compiler (it compiles the example with covariant return types)

[Edited by - MaulingMonkey on October 16, 2004 10:19:59 PM]

This topic is closed to new replies.

Advertisement