Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

Virtual Constructors

Posted on 2002-07-24
14
Medium Priority
?
1,311 Views
Last Modified: 2013-11-15
Why can't we have virtual constructors?
0
Comment
Question by:SPrasanna
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
  • 3
  • 3
  • +3
14 Comments
 
LVL 4

Expert Comment

by:IainHere
ID: 7173953
In the words of Bjarne Stroustup (P424 The C++ Programming Language SE)

"To construct an object, a constructor needs the exact type of the object it is to create [...] Furthermore [...]you cannot have a pointer to a constructor"

If you just ask out of interest, that might do you.  If you actually need a virtual constructor, create a virtual member function, which calls the constructor for you:

virtual baseClass* clone() { return new baseClass(*this) };

and in the derived class:

derivedClass* clone() { return new derivedClass(*this) };

However, this exact approach doesn't work in VC++6, you'll need to return a pointer to the base class in both functions, but this can be good enough in some cases.
0
 
LVL 30

Expert Comment

by:Axter
ID: 7174191
Sounds like homework.......
0
 
LVL 22

Expert Comment

by:nietod
ID: 7174680
Think about how a virtual function behaves.   It provides polymorphic behavior.  That is, when you work with an object whose actual type is different than the static (compile time) type with which it is referred to, it provides behavior that is appropriate for the _actual_ type of object instead of the static type of the object.

Now try to apply that sort of behavior to a constructor.   How can you?  its nonesense.   When you construct an object the static type is always the same as the actual object type.   So you always get the correct behavior of the constructor without requiring the constructor to be virtual.

>> If you actually need a virtual constructor, create a virtual member function,
>> which calls the constructor for you:
That is a useful technique, but it is not a constructor or even that similar to a constructor.

>> this exact approach doesn't work in VC++6,
It works for me!  Once you fix the fact that the derived class needs to return a value of the same type as the base class.
0
Use Case: Protecting a Hybrid Cloud Infrastructure

Microsoft Azure is rapidly becoming the norm in dynamic IT environments. This document describes the challenges that organizations face when protecting data in a hybrid cloud IT environment and presents a use case to demonstrate how Acronis Backup protects all data.

 
LVL 1

Expert Comment

by:ris
ID: 7174779
I think a good example of what IainHere has mentioned is in the MFC class: CRuntimeClass, and it's function CObject* CRuntimeClass::CreateObject().

In addition, consider the syntax of virtual functions... how could you specify a virtual constructor when the constructor function name has to match the class name and a virtual function name has to match the base class virtual function name: you can't do both.  To have virtual constructors, you'd have to radically change the language syntax.

Like Axter said, this sounds like homework... If it is, then you are robbing yourself of an education by coming here for the answers when you could be reading your text book and paying attention to class lectures instead.  If it's not homework, then I apologize for coming down on you about it.
0
 
LVL 9

Expert Comment

by:jasonclarke
ID: 7175530
> Once you fix the fact that the derived class needs to
> return a value of the same type as the base class.

it should work anyway, of course, this is an example of a covariant return type, which is valid standard C++ but is not legal VC++ 6.0.  (I think this may actually be fixed in VC++ 7, but I would have to check).
0
 
LVL 4

Expert Comment

by:IainHere
ID: 7176605
>>It works for me!  Once you fix...
I thought I said that   :-)
0
 

Author Comment

by:SPrasanna
ID: 7177103
In Mr.Ris's words ,we can't have virtual constructors since
     "the constructor function name has to match the class name and a virtual function name has to match the base class virtual function name: you can't do both"

but,
    destructors are same as constructors and we can have virtual destructors.Of course we must have in some cases,which contradicts with Mr.Ris's words.
    Could u please clear it to me Mr.Ris?
(I am sure u won't think it as a homework now Mr.Ris?)

0
 

Author Comment

by:SPrasanna
ID: 7177114
In Mr.Ris's words ,we can't have virtual constructors since
     "the constructor function name has to match the class name and a virtual function name has to match the base class virtual function name: you can't do both"

but,
    destructors are same as constructors and we can have virtual destructors.Of course we must have in some cases,which contradicts with Mr.Ris's words.
    Could u please clear it to me Mr.Ris?
(I am sure u won't think it as a homework now Mr.Ris?)

0
 
LVL 9

Accepted Solution

by:
jasonclarke earned 200 total points
ID: 7177154
> but, destructors are same as constructors and we can
> have virtual destructors

they really are not the same at all.  The whole point is constructors must *always* be called *explicitly*, by naming the exact class to construct (i.e. the call to the constructor).

Destructors are very different in this respect, when an object is destroyed, you may only have a reference to a base class, and hence the run-time may need to decide (via the virtual call mechanism), which destructors to call.

i.e. think about:

Base* b = new Derived;
delete b;  // What happens here?

BTW, IainHere, sorry I missed you point, which as you said explained the situation wrt covariant return in VC++ 6.  And, it is definitely fixed in VC++ 7.
0
 
LVL 9

Expert Comment

by:jasonclarke
ID: 7177218
eeek,  I am not really sure I deserve the points for this question:  in general you should give points to the person who answered your -original- question; IainHere in particular may feel somewhat unhappy in this case.  I provided no assistance whatsoever with that (other than to clarify a point of information) here.  

If you feel that answers to supplementary questions you receive deserve points, you should probably award them separately (i.e. in Points For style).

But thanks anyway.
0
 
LVL 4

Expert Comment

by:IainHere
ID: 7177269
No complaints  :-)
0
 

Author Comment

by:SPrasanna
ID: 7177283
Sorry Mr.ianhere, actually am new to the exchange,and new to awarding points.
0
 
LVL 1

Expert Comment

by:ris
ID: 7177353
Well, you already accepted an answer, but I have a few more comments that it seems useful to mention, so I figure I might as well...

The syntactical issue of declaring a virtual destructor is a special case.  Consider that all classes have a single destructor function (even if it is implied) that takes no arguments and has no return value.  Since that is the case, there is no need to have a matching name for the virtual functions in both the base and derived classes.  However, a class can have multiple constructors, which makes it somewhat more complicated to decide which constructor is being overriden if you could specify more than one as virtual.  I suppose that as complex as it would become, it would be possible to create a clear syntax for virtual constructors if you put your mind to it, but it would still be impossible to implement because of the vtable...

Virtual functions are implemented using a table of function pointers, called the vtable.  There is one entry in the table per virtual function in the class.  This table is created by the constructor of the class.  When a derived class is constructed, its base class is constructed first which creates the vtable.  If the derived class overrides any of the base classes virtual functions, those entries in the vtable are overwritten by the derived class constructor.  This is why you should never call virtual functions from a constructor: because the vtable entries for the object may not have been set up by the derived class constructor yet, so you might end up calling base class implementations of those virtual functions.  Some compilers can output modified code that sets up the complete vtable before executing the rest of the constructor code so that you can call virtual functions virtually from a constructor.  It's compiler-specific.  I don't know what the official standard is on that point, but I think it is a better idea just to not call virtual functions from constructors.  If you need something like that, you are better off creating a virtual void Init() function that you call on all your objects after you construct them.

Anyway, because the vtable is created by the constructor, you don't have a vtable yet at the time you call the constructor, and so there no way to have a pointer to a virtual override of that function, because there's no object yet in which to store a vtable in which to store a pointer to a virtual constructor.

Even if you found a way to implement virtual constructors without an object with a vtable, they would still be useless.  Consider this code:

class Base
{
  virtual Base(); //virtual constructor
}

class Derived : public Base
{
  virtual Derived(); //virtual override constructor
}

Now what happens if you call "new Base();"?  Are you creating a Base object or a Derived object?  If you are creating a Base object, then the constructor must not be a virtual function.  And if you are creating a Derived object, then you have lost the ability to create a Base object because calling "new Base" is equivalent to "new Derived."  What if there are two derived classes, each with virtual overrides of the constructor.  Then what would happen?  So the whole virtual constructor concept is either meaningless or a hindrance.

So as you can see, there are quite a few reasons why we can't have virtual constructors.
0
 
LVL 22

Expert Comment

by:nietod
ID: 7682888
>> However, a class can have multiple constructors,
>> which makes it somewhat more complicated to
>> decide which constructor is being overriden if you
>> could specify more than one as virtual.
Well, that argument would then say that you couldn't have overloaded virtual "ordinary" functions.  i..e functions that are not constructors or destructors, that are overoads, and that are virtual.  Of course we can have these (although often their use is a bad idea.)

>>  it would be possible to create a clear syntax for virtual constructors
we have the syntax.  We use it for non-constructors.  The problem is not syntax, its logic.  A virtual constructor is not a logical concept.  If we had them, they would always function exactly the same as non-virutal constructors.  Thus there is no need for them.

>> Virtual functions are implemented using a table of
>> function pointers, called the vtable.
That is an implimentation detail.  Some compilers could impliment them in a different manner.  (although that is doubtful.)

>> This table is created by the constructor of the class.
Again this implimentation dependant, but I doubt any implimentation would ever do this.  Typically the tables are created at compile-time and stored in static memory.  All objects of a particular class will share the same table.  The constructor meerly sets up a pointer to the table, not the table itself.

>>  If the derived class overrides any of the base classes virtual
>> functions, those entries in the vtable are overwritten by the
>> derived class constructor.
Agian typically not.  All objects of the derived class usually uses a distinct table from the one used by all objects of the base class.  The constructor and destructor mearly adjust the pointer to the table, not the table.

>> This is why you should never call virtual functions from a constructor
It is perfectly safe to call vitual functions from a constructor and destructor.  However, go need to understand their behavior.  During construction of a base class, for puposes of virtual functions and RTTI the object is considered to be of the base class type, even if there are further derived classes to be constructed.  Similarrly during destruction the object is considered to be the base class type during the destruction of the base class, even if there were derived classes that were previously destroyed.  i..e the object's effective typ changes during the construction and destruction process.  

>> Some compilers can output modified code that sets
>> up the complete vtable before executing the rest of the
>> constructor code so that you can call virtual functions
>> virtually from a constructor.  It's compiler-specific.
Not at all.  The behavior of virtual functions called from a constructor/destructor is specified by the C++ standard.

>> Even if you found a way to implement virtual constructors without an
>> object with a vtable, they would still be useless.
Yes.  That is the point.

>> Now what happens if you call "new Base();"?  Are you creating a Base
>> object or a Derived object?
You are creating a base object.  There can be no doubt about it.  That is why virtual constructors are never needed.  We always know what we are creating thus we always know what constructor(s) to call without the aid of virtual functions.  Virtual behavior makes no sense in this case.
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

VM backup deduplication is a method of reducing the amount of storage space needed to save VM backups. In most organizations, VMs contain many duplicate copies of data, such as VMs deployed from the same template, VMs with the same OS, or VMs that h…
Your data is at risk. Probably more today that at any other time in history. There are simply more people with more access to the Web with bad intentions.
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.

722 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question