3

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.

fred
  • 31
  • 2
  • Could you show some code to more clearly illustrate what the problem is? I have some possible solutions mulling around in my head, but I'm not exactly sure which ones if any apply to your problem. – Benjamin Lindley Oct 27 '10 at 10:24
  • The problem is that it's quite a lot of code spread out over 3 files, with overloaded methods in each of them. I really think it's hard to make it clearer than in a textual general description. But if I can figure out just what to post I will. – fred Oct 27 '10 at 10:29
  • Are you calling the virtual function on the object being *copied* in the copy ctor, or on the object being *constructed* (`this`)? The former is fine (as long as the parameter is taken by reference). The latter isn't. – Steve Jessop Oct 27 '10 at 10:59
  • By the way, the reason that a copy ctor (or any ctor) can't be virtual, is that constructors aren't inherited at all. The copy ctor defined in your base class will *never* create an object of the derived class (although it could be used to create the base class sub-object of one). – Steve Jessop Oct 27 '10 at 11:05

6 Answers6

6
  1. Be careful about calling virtual methods in base class constructors.
  2. You may want to use a clone-method.
Community
  • 1
  • 1
Björn Pollex
  • 75,346
  • 28
  • 201
  • 283
3

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.,

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
  • 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 Oct 27 '10 at 10:45
  • @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, – Cheers and hth. - Alf Oct 27 '10 at 10:51
  • @fred: I think one problem here is simply *terminology*. A "copy constructor" of a class T always takes an argument of type T cv&, where cv can be nothing, const, volatile or const volatile. So in the copy constructor you (effectively) have an argument of type T. Some other constructor might take an argument of a different type. That constructor is then a conversion constructor. One way to solve your problem is to have both a copy constructor and a conversion constructor in each class. Cheers, – Cheers and hth. - Alf Oct 27 '10 at 11:49
  • 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 Oct 27 '10 at 11:56
1

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
  • 726
  • 6
  • 17
0

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.

Eugene Smith
  • 9,126
  • 6
  • 36
  • 40
  • 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 Oct 27 '10 at 10:33
0

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
  • 30,981
  • 5
  • 61
  • 92
  • Thanks, what I do is more like this where the init method is virtual: ` T:T(const T& other){ internal_var = other.get_internal_var(); init(internal_var); } ` – fred Oct 27 '10 at 11:50
  • Sorry for that mess, I don't have much luck with these code tags. – fred Oct 27 '10 at 11:52
0

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
  • 53,498
  • 9
  • 91
  • 140