Sign in to follow this  
JimPrice

Copy constructor / assignment with abstract classes

Recommended Posts

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.

Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites
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); }

};

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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 derived
D1 * 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]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this