Solved

Virtual Constructors

Posted on 2002-07-24
14
1,259 Views
Last Modified: 2013-11-15
Why can't we have virtual constructors?
0
Comment
Question by:SPrasanna
  • 3
  • 3
  • 3
  • +3
14 Comments
 
LVL 4

Expert Comment

by:IainHere
Comment Utility
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
Comment Utility
Sounds like homework.......
0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
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
 
LVL 1

Expert Comment

by:ris
Comment Utility
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
Comment Utility
> 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
Comment Utility
>>It works for me!  Once you fix...
I thought I said that   :-)
0
 

Author Comment

by:SPrasanna
Comment Utility
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
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 

Author Comment

by:SPrasanna
Comment Utility
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 50 total points
Comment Utility
> 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
Comment Utility
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
Comment Utility
No complaints  :-)
0
 

Author Comment

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

Expert Comment

by:ris
Comment Utility
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
Comment Utility
>> 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

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
Are you looking to recover an email message or a contact you just deleted mistakenly? Or you are searching for a contact that you erased from your MS Outlook ‘Contacts’ folder and now realized that it was important.
This tutorial will walk an individual through the steps necessary to enable the VMware\Hyper-V licensed feature of Backup Exec 2012. In addition, how to add a VMware server and configure a backup job. The first step is to acquire the necessary licen…
To efficiently enable the rotation of USB drives for backups, storage pools need to be created. This way no matter which USB drive is installed, the backups will successfully write without any administrative intervention. Multiple USB devices need t…

763 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

Need Help in Real-Time?

Connect with top rated Experts

9 Experts available now in Live!

Get 1:1 Help Now