4

I have two questions and the answers I found here didn't totally satisfy me:

  • Why declaring a constructor as virtual is meaningless?
  • What happens when I call a virtual function from a constructor? Is the virtual table used too?
Johnny Pauling
  • 12,701
  • 18
  • 65
  • 108
  • What does "get walked" mean? – Beta Apr 10 '13 at 19:52
  • This related question has some good information: http://stackoverflow.com/questions/962132/calling-virtual-functions-inside-constructors – Chad Apr 10 '13 at 19:56
  • If _the answers you found here_ didn't satisfy you, please link to those answer and explain _why_ they didn't satisfy you, lest we repeat the mistake. – Björn Pollex Apr 10 '13 at 19:59
  • Its a repeated followup question in SO http://stackoverflow.com/questions/962132/calling-virtual-functions-inside-constructors – shivakumar Apr 10 '13 at 19:59
  • 2
    this may be of interest: http://www.parashift.com/c++-faq/virtual-ctors.html – Ray Tayek Apr 10 '13 at 20:10

3 Answers3

3

Why declaring a constructor as virtual is meaningless?

Before the constructor is executed, the object does not exists, so there is no such thing as an override.

What happens when I call a virtual function from a constructor? Is the virtual table used too?

It can. In most cases, if the call is directly performed from the constructor the compiler can skip the dynamic dispatch, as it knows what the final overrider is at this point. But it need not perform that optimization, and even if it can do that in the constructor directly, it cannot do it if you call a non-virtual function that in turn calls the virtual function. Because the non-virtual function might be called for objects of derived types it must use the virtual dispatch mechanism.

David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489
2

When calling a constructor, the actual type of the (not yet existing) object is known for very sure. So calling a constructor will never be indirect. (Only virtual functions are called indirectly when called via a pointer / reference.)

BaseClass *x = new SubClass();

Calling a virtual function in a constructor doesn't do what you might expect. As the subclass hasn't been initialized yet, the virtual function on the final class can't be called (the v-table currently points to the class of the constructor currently being executed).

class BaseClass {
    BaseClass() {
        call();
    }
    virtual void call() {
        std::cout << "BaseClass!";
    }
};

class SubClass : public BaseClass {
    SubClass() : BaseClass()
    {
    }

    void call() {
        std::cout << "SubClass!";
    }
};

http://ideone.com/9aQVIc

leemes
  • 44,967
  • 21
  • 135
  • 183
  • 1
    Calling a virtual function from a constructor **is not** undefined behavior. It is perfectly defined in the standard to call the *final overrider* at the level of the type being constructed. – David Rodríguez - dribeas Apr 10 '13 at 19:57
  • Corrected. I wasn't sure; I knew I'd remember it incorrectly. Now I remember. See my correction. – leemes Apr 10 '13 at 19:59
  • @David So just to clarify, if you had `class SubSubClass : public SubClass`, and you tried to call `call()` from `SubClass`'s constructor, it would call `SubClass::call()`? – JBentley Apr 10 '13 at 20:03
  • Yes. When the constructor of a class is being called, it's the same as you were actually constructing an instance of exactly this class (and not a subclass). (Indeed, in this very moment, an instance of this class *is* being constructed. Nothing more until then. The constructor of a subclass always first calls the super class constructor.) – leemes Apr 10 '13 at 20:04
  • @JBentley: In C++ the type of an object changes during construction/destruction. At each level it is the type of the constructor/destructor being called. So yes, the code `call();` inside the constructor of `SubClass` won't be dispatched below the `SubClass` point in the hierarchy, even if the complete object being built is a `SubSubSub...Class`. – David Rodríguez - dribeas Apr 10 '13 at 20:12
  • @David But when SubClass is being constructed, that means BaseClass is already constructed, so doesn't `call()` inside the `SubClass` constructor have two virtual functions to choose from (`SubClass::Call()` and `BaseClass::Call()`? I take your point that `call()` won't be dispatched *below* `SubClass`, but what about *above*? – JBentley Apr 10 '13 at 20:24
  • Calling `call()` inside `SubClass` will then call `SubClass::call()`, yes. – leemes Apr 10 '13 at 20:34
1

Why declaring a constructor as virtual is meaningless.

When the constructor is invoked the virtual table would not be available in the memory. Declaring something virtual in C++ means that it can be overridden by a sub-class of the current class, however the constructor is called when the objected is created, at that time you can not be creating a sub-class of the class you must be creating the class so there would never be any need to declare a constructor virtual. Therefore, there is no such a thing as virtual constructor in C++.

What happens when I call a virtual function from a constructor? Is the virtual table used too

See C++ FAQ link about detailed explanation of this question.

taocp
  • 23,276
  • 10
  • 49
  • 62