views:

99

answers:

6

Hi,

I have an abstract base class with two inherited classes. In both these classes I define a virtual method that is used by the constructor. Now I need to create a copy constructor, but I can not declare the copy constructor as virtual, but I want the method call inside it to be dependent on the type of object that is fed as argument. How can I solve this?

Right now I use the base class to define the type of argument, this doesn't work since the method I call inside the copy constructor is not defined in the base class.

Basically I need the copy constructor to be virtual.

+5  A: 
  1. Be careful about calling virtual methods in base class constructors.
  2. You may want to use a clone-method.
Space_C0wb0y
Thanks, I will take a look at the clone-method in that link.
fred
A: 

Create a virtual method in the object that's passed as an argument to the copy constructor, and call it from the copy constructor. Pass 'this' to that method if necessary.

That sounds like what I am doing now, but since I want to be able to pass arguments of both derived classes, I need to declare the base class as the argument. Would this be enough for the recognition of the type at run-time? If so my problem might be elsewhere, it compiles but the result makes no sense. If I restrict the type to one of the base classes, it works but, only on the type that is in the declaration.
fred
+1  A: 

Virtual functions called during the constructor/destructor won't resolve to derived type. As stated by Scott Myers here -

During base class construction, virtual functions never go down into derived classes. Instead, the object behaves as if it were of the base type.

since you can't use virtual functions to call down from base classes during construction, you can compensate by having derived classes pass necessary construction information up to base class constructors instead.

Hemant
+3  A: 

In a copy constructor of class T you know that the object to be copied is of class T.

A copy constructor can not construct an object of a derived class.

It's the derived class' copy constructor that constructs the derived part.

So you're confused about something: the question does not make sense.

Presenting an example might clear up what exactly the confusion is about.

Cheers & hth.,

Alf P. Steinbach
Thanks, the implementation is in the derived classes. But if I have the derived classes A and B, I would like to make an A from a B like so: `A a(b);`
fred
@fred: That's a conversion. For converting from B to A you can either provide a constructor in A that takes a B argument, or you can provide an `operator A` in class B. Cheers,
Alf P. Steinbach
Ok, thanks. I guess so, but I really would like to be able to do all of the following: `A a(a2);` `A a(b);` `B b(a);` `B b(b2);` I have the methods to do the conversion, I just need the copy constructor to recognize if it gets an object of type A or B, and use the appropriate method at run-time.
fred
Alf P. Steinbach
Thank you, you are right about the terminology, C++ is pretty new for me. Creating one of each would certainly solve the problem as far as I can tell by now.
fred
A: 

We'd have to know exactly what you are trying to achieve to know what the right solution is.

However there is no problem in calling a virtual function on the object being copied, as that is already a fully constructed object. You can also feed the "this" into it, as long as that function knows that the pointer being passed in is not fully constructed yet. Thus:

T::T( const T & other )
{
   other.some_virtual_method(this); // legal but potentially dangerous
}

void T::some_virtual_method( T* other ) const
{
   other->another_virtual_method(); // dangerous in this situation
}
CashCow
Thanks, what I do is more like this where the init method is virtual: ` T:T(const T init(internal_var);}`
fred
Sorry for that mess, I don't have much luck with these code tags.
fred
A: 

There is a nice discussion of the Prototype Pattern here which could be helpful.

Prototype [Go4]

Problem

A "factory" class can't anticipate the type of "product" objects it must create.

Solution

Derive all product classes from an abstract Product base class that declares a pure virtual clone() method. The Product base class also functions as the product factory by providing a static factory method called makeProduct(). This function uses a type description parameter to locate a prototype in a static prototype table maintained by the Product base class. The prototype clones itself, and the clone is returned to the caller.

The reference to 'Go4' is for the seminal book on Design Patterns written by the "Gang of Four" authors.

Steve Townsend