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?
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.
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
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.
Related
I was trying to familiarize myself with the OOP concepts but could not quite understand the concept of virtual.
One can create a virtual destructor but not a virtual constructor. Why?
How are virtual destructors handled internally? I mean the link Virtual Destructors illustrates the concept but my question is how the vptr of both the vtables (Derived and Base) are called? (In case of virtual member functions when such a scenario occurs generally the function that vptr of Derived class points to is only called)
Are there any other scenarios where one may need to use a virtual destructor?
Can anyone please help me understand the above concepts with links/examples?
First, a little about the difference between virtual functions and non-virtual functions:
Every non-virtual function-call that you have in your code can be resolved during compilation or linkage.
By resolved, we mean that the address of the function can be computed by the compiler or the linker.
So in the object code created, the function-call can be replaced with an op-code for jumping to the address of that function in memory.
With virtual functions, you have the ability to invoke functions which can be resolved only during runtime.
Instead of explaining it, let's run through a simple scenario:
class Animal
{
virtual void Eat(int amount) = 0;
};
class Lion : public Animal
{
virtual void Eat(int amount) { ... }
};
class Tiger : public Animal
{
virtual void Eat(int amount) { ... }
};
class Tigon : public Animal
{
virtual void Eat(int amount) { ... }
};
class Liger : public Animal
{
virtual void Eat(int amount) { ... }
};
void Safari(Animal* animals[], int numOfAnimals, int amount)
{
for (int i=0; i<numOfAnimals; i++)
animals[i]->Eat(amount);
// A different function may execute at each iteration
}
As you can probably understand, the Safari function allows you to be flexible and feed different animals.
But since the exact type of each animal is not known until runtime, so is the exact Eat function to be called.
The constructor of a class cannot be virtual because:
Calling a virtual function of an object is performed through the V-Table of the object's class.
Every object holds a pointer to the V-Table of its class, but this pointer is initialized only at runtime, when the object is created.
In other words, this pointer is initialized only when the constructor is called, and therefore the constructor itself cannot be virtual.
Besides that, there is no sense for the constructor to be virtual in the first place.
The idea behind virtual functions is that you can call them without knowing the exact type of the object with which they are called.
When you create an object (i.e., when you implicitly call a constructor), you know exactly what type of object you are creating, so you have no need for this mechanism.
The destructor of a base-class has to be virtual because:
When you statically allocate an object whose class inherits from the base-class, then at the end of the function (if the object is local) or the program (if the object is global), the destructor of the class is automatically invoked, and in turn, invokes the destructor of the base-class.
In this case, there is no meaning to the fact that the destructor is virtual.
On the other hand, when you dynamically allocate (new) an object whose class inherits from the base-class, then you need to dynamically deallocate (delete) it at some later point in the execution of the program.
The delete operator takes a pointer to the object, where the pointer's type may be the base-class itself.
In such case, if the destructor is virtual, then the delete operator invokes the destructor of the class, which in turn invokes the destructor of the base-class.
But if the destructor is not virtual, then the delete operator invokes the destructor of the base-class, and the destructor of the actual class is never invoked.
Consider the following example:
class A
{
A() {...}
~A() {...}
};
class B: public A
{
B() {...}
~B() {...}
};
void func()
{
A* b = new B(); // must invoke the destructor of class 'B' at some later point
...
delete b; // the destructor of class 'B' is never invoked
}
One can create a virtual destructor but not a virtual constructor. Why?
Virtual functions are dispatched according to the type of the object they're called on. When a constructor is called, there is no object - it's the constructor's job to create one. Without an object, there's no possibility of virtual dispatch, so the constructor can't be virtual.
How are virtual destructors handled internally?
The internal details of virtual dispatch are implementation-defined; the language doesn't specify the implementation, only the behaviour. Typically, the destructor is called via a vtable just like any virtual function.
how the vptr of both the vtables (Derived and Base) are called?
Only the most-derived destructor will be called virtually. All destructors, virtual or not, will implicitly call the destructors of all member and direct base-class subobjects. (The situation is slightly more complicated in the presence of virtual inheritance; but that's beyond the scope of this question).
Are there any other scenarios where one may need to use a virtual destructor?
You need one in order to support polymorphic deletion; that is, to be able to delete an object of derived type via a pointer to a base type. Without a virtual destructor for the base type, that's not allowed, and will give undefined behaviour.
because a Virtual function is invoked at runtime phase, however constructors are invoked at initialization phase, object is not constructed. So it's meaningless to have a virtual constructor.
a. the reason why only the base class desctructor is invoked in your link, the destructor is not marked as virtual, so the desctructor address is linked to Base class destructor at compile/link time, and obviously the type of the pointer is Base instead of Derived at compile time.
b. for why both of Base and Derived constructors are invoked after adding virtual to Base desctructor. It's same behavior like below:
Derived d; // when d exits the lifecycle, both Derived and Base's desctructor will be invoked.
Suppose when you have at least one virtual function, you should have a virtual desctructor.
One can create a virtual destructor but not a virtual constructor.
Why?
I'll try and explain this in layman's terms.
A class in c++ only exists after it's constructor completes. Each base class exists prior to initialisation of derived class and its members (vtable links included). Hence, having a virtual constructor does not make sense (since to construct, you need to know the type). Furthermore (in c++), calling virtual functions from a constructor does not work (as the derived class's vtable part has not been set up). If one thinks about it carefully, allowing virtual functions to be called from a contructor opens up a can of worms (such as what if virtual functions of derived classes are called prior to member initialization).
As far as destructors are concerned, at the point of destruction, the vtable is "intact", and we (c++ runtime) are fully aware of the type (so to speak). The destructor of the most derived part of the type is found (if virtual, through vtable), and therefore that destructor, and naturally that of all bases can be called.
How are virtual destructors handled internally? I mean the link
Virtual Destructors illustrates the concept but my question is how the
vptr of both the vtables (Derived and Base) are called?
Destructors are handled the same as normal virtual functions (that is, there addresses are looked up in a vtable if they are virtual at the expense of one (perhaps 2?) extra level/s of indirection). Furthermore, c++ guarantees that all base destructors shall execute (in opposite order of construction which relies on order of declaration) after completion of a derived destructor.
One can mimick/simulate virtual construction by using patterns such as the prototype pattern (or cloning), or by using factories. In such cases either an instance of the real type exists (to be used polymorphically), or a factory exists (deriving from abstract factory), that creates a type (via virtual function) based on some knowledge provided.
Hope this helps.
I assume we have a Base class A, and it's derived B.
1.: You can delete B via an A pointer, and then the correct method is to call the B destructor too.
However, you just can't say, that a B object should be created while you actually just call the A constructor. There is just not such a case.
You can say:
A* a = new B ();
or
B b;
But both directly call the B's constructor.
2.: Well, i am not entirely sure, but i guess it will iterate through the relevant part of the class hierarchy, and search for the closest call of the function. If a function is not virtual, it stop iterating and call it.
3.: You should always use virtual destructor, if you want to inherit something from that class. If it's a final class, you shouldn't.
I wasted a couple of days trying to discover why my derived virtual destructors were not being called before discovering the answer so hopefully I can save other a lot of grief with this reply.
I started using derived classes three and four levels deep in my project. Virtual functions seemed to work fine but then I discovered I had massive memory leaks because my destructors were not being called. No compiler or runtime error - the destructors just were not being called.
There is a ton of documentation and examples about this on the web but none of it was useful because my syntax was correct.
I decided that if the compiler wasn't going to call my destructors, I needed to create my own virtual destruct method to call. Then I got the compiler error that solved the problem - "class if a Forward Reference". Adding an include for the derived class header files in the base class solved the problem. The compiler needs the class definition to call the destructor!
I suggest when creating a new derived class, include the header file in the base and intermediate classes. Probably also a good idea to add conditional debug code to your destructors to check that they are bing called.
Bob Rice
class A
{
public:
...
virtual bool Function(..) const {...}
}
class B : public A
{
public:
...
virtual bool Function(..) const {...}
}
class OtherClass
{
public:
OtherClass(A& a)
{
m_bool = a.Function(..);
}
private:
bool m_bool;
}
Assume that class A or class B are fully initialized before the construction of class OtherClass.
Question> Is there a problem regarding the calling of a virtual function in the constructor of OtherClass?
No, why should there be any problem? The instance of A passed (via reference) to the constructor of OtherClass is already fully initialized, so virtual functions on it work as expected.
The warning you heard is about calling virtual functions of the object you are constructing inside its constructor; in this case, virtual dispatch is disabled, i.e. in the constructor of each base class the virtual function version called is the one of the base class whose constructor is running.
The idea is that, inside a base class constructor, the object isn't yet become of its final type; in other words, while you are constructing an object that inherits from some base class, it starts as the "basest" type, and transitions to derived types when each derived-class constructor is run. This reflects in what versions of virtual functions the various constructors see when they are run.
You can read about it in more detail here.
Again, this does not affect any object that is passed to the constructor, since they are already fully constructed, so their "definitive type" (and thus the corresponding set of virtual functions) is already completely established.
If the functions are defined and not pure virtual functions or abstract base classes, the function call should be fine. the a object will call its virtual function as expected, so to answer your question, no.
Calling virtual function of A/B has nothing to do with whether it's called from OtherClass's constructor or anywhere else. So no issue.
I have some code where I really want to call a virtual method from a constructor. I know this is considered unsafe, and I know enough about object construction to also understand why. I also am not experiencing these problems. Currently my code is working and I think it should be fine, but I want to make sure.
Here is what I am doing:
I have some class hierarchy and there is a normal public function which just forwards to a private virtual method, as usual. However I do want to call this public method upon construction of my objects, because it is filling all data into the object. I will be absolutely sure that this virtual call comes from the leaf class, because using this virtual method from any other part of the class hierarchy simply does not make sense at all.
So in my opinion the object creation should be finished once I am doing the virtual call and everything should be fine. Is there still anything that could go wrong? I guess I'll have to mark this part of the logic with some big comments to explain why this logic should never ever be moved to any of the base clases, even though it looks like it could be moved. But other than stupidity of other programmers I should be fine, shouldn't I?
It is absolutely safe to call any non-abstract virtual function in the constructor or the destructor! However, its behavior may be confusing as it may not do what is expected. While the constructor of a class is executed, the static and dynamic type of the object is the type of the constructor. That is, the virtual function will never be dispatched to the override of a further derived class. Other than that, virtual dispatch actually works: e.g. when calling a virtual function via a base class pointer or reference correctly dispatches to the override in the class being currently constructor or destructed. For example (probably riddled with typos as I currently can't this code):
#include <iostream>
struct A {
virtual ~A() {}
virtual void f() { std::cout << "A::f()\n"; }
void g() { this->f(); }
};
struct B: A {
B() { this->g(); } // this prints 'B::f()'
void f() { std::cout << "B::f()\n"; }
};
struct C: B {
void f() { std::cout << "C::f()\n"; } // not called from B::B()
};
int main() {
C c;
}
That is, you can call a virtual function, directly or indirectly, in the constructor or a destructor of a class if you don't want the virtual function to be dispatched to a further derived function. You can even do this is virtual function is abstract in the given class as long as it is defined. However, having an undefined abstract function being dispatched to will cause a run-time error.
When a constructor is called, the class is set up to be an instance of that class but not the derived class. You cannot call into a virtual function of a derived class from a base constructor. By the time you get to the constructor of the most derived class, all of the virtual functions should be safe to call.
If you wish to ensure that someone can't make an incorrect call, define the virtual function in the base class and have it assert and/or throw an exception when it is called.
The rule isn't so much that you need to be in a leaf class as to realize that when you make a member call from Foo::Foo(..), the object is exactly a Foo, even if it's on its way to being a Bar (assuming Foo is derived from Bar and you're constructing a Bar instance). That's 100% reliable.
Otherwise, the fact that the member is virtual isn't all that significant. There are other pitfalls that happen just as well with non-virtual functions: if you were to call a virtual or non-virtual method that assumed the object was completely constructed but called it within the constructor before that was the case, you'd also have problems. These are just hard cases to pin down because not only must the function you call be okay, all the functions it calls must be okay.
It doesn't sound like you have a problem, it's just one of those places prone for errors to crop up.
I find this strange. In the ctor of Sample_Base, I call bar() which internally calls fun() which is a pure virtual function. I get the error "pure virtual function" called. Which is fine. Now, if I call fun() directly from Sample_Base's ctor, I don't get that error. I tried it on VC++ 2010 Beta 2 and on g++ 4.4.1 on Ubuntu 9.10. I agree that giving an implementation for pure virtual function, other than pure virtual destructor, is meaningless. But, I am a bit surprised about this behaviour.
class Sample_Base
{
public:
Sample_Base()
{
bar();
// fun();
}
/* This is code does not throw any error.
Sample_Base()
{
fun();
}
*/
void bar()
{
fun();
}
virtual void fun() = 0;
virtual ~Sample_Base();
};
Sample_Base::~Sample_Base()
{
}
void Sample_Base::fun()
{
std::cout << "Sample_Base::fun\n";
}
class Sample_Derived : public Sample_Base
{
public:
Sample_Derived() : Sample_Base()
{
fun();
}
void fun()
{
std::cout << "Sample_Derived::fun\n";
}
~Sample_Derived()
{
}
};
When you call the function directly, since you are in the constructor, the compiler resolves the static type of your object (Sample_Base) and calls Sample_Base::fun() directly. Since you provided an implementation for it, the compiler finds the function and it works.
When you call it indirectly, through bar(), the compiler must use the dynamic type, so it does a virtual call that gets resolved at runtime. And there it fails, because it calls a pure virtual function.
So the difference is in the moment it binds the function to the call.
Providing a definition for a pure virtual function is not necessarily meaningless. Marking a virtual function pure means that the enclosing class is abstract and that any class that derives from it is abstract unless the final override for that function is not a pure virtual function. A pure virtual function can still be called via an explicit non-virtual call.
In the body of a base class constructor (but not from a ctor-initializer) the version of a virtual function called through a virtual call is one defined in the class itself or one of its bases and not of any class overriding it (which would not yet have been constructed). This is specified explicitly in 12.7 [class.cdtor]/3.
It is legal to call a pure virtual function explicitly in a constructor body (i.e. using an explicit class qualifier) - although this would required the function to have a body defined - but it is undefined behaviour to call a pure virtual function via a virtual call which is only possible from the constructor or destructor of an abstract class. This is specified explicitly in 10.4 [class.abstract]/6.
At construction time, when the Sample_Base constructor is called, the object is not fully constructed yet. Specifically the parts belonging to Sample_Derived are not yet created calls to virtual functions that would be overwritten by Sample_Derived will not call the implementation in Sample_Derived, but the version defined in Sample_Base. And since the function has no implementation there you get an error.
For more information and possible workarounds also see this entry in the C++ FAQ Lite.
Calling a virtual function won't call the overriding functions in the derived classes. Calling a pure virtual function in a constructor or destructor is Undefined behavior.
You might be interested in reading this and this.
This behavior is not undefined, it's explicitly defined: virtual functions are not virtual in constructors and destructors. They call the static version of the function. If the function is pure virtual, this results in the famous "pure virtual call" error in VC.
I've seen an amusing variation of this in a multithreaded program: an object is being destructed on thread A, while thread B is attempting to call a virtual function. There was no virtual function call in the constructor or destructor, but we still got hit with a pure virtual call error.
Sorry if this is a dupe, I cant find an answer quite right.
I want to call a function from a base class member, and have it resolve to the subclass version. I thought declaring it virtual would do it, but it isn't. Here's my approach:
class GUIWindow
{
public:
GUIWindow()
{
SetupCallbacks();
}
virtual void SetupCallbacks()
{
// This function always called
}
};
class GUIListbox : public GUIWindow
{
public:
void SetupCallbacks()
{
// This never called
}
};
GUIListbox lb; // GUIWindow::SetupCallbacks is called :(
What am I doing wrong?
Many thanks
Si
Never call a virtual function in the constructor.
When you call virtual functions during construction of some class C (i.e. while the constructor of C is active), the virtual mechanism works, but it works in restricted mode. The resolution of the virtual calls in the class hierarchy is limited by the class that is currently being constructed (C). This means that the virtual calls will resolve as if the class C is the "final" class in the hierarchy, as if it has no descendants.
The same is true for destructors.
In your example, you are calling a virtual function from constructor of class GUIWindow. As long as the constructor of GUIWindow is active, its virtual mechanism will work as if there are no other classes derived from GUIWindow. This mechanism will completely ignore the existence of GUIListbox class. This is why the resolution of virtual call "stops" at GUIWindow and calls GUIWindow::SetupCallbacks, as if GUIListbox::SetupCallbacks doesn't exist.
You can read about in in C++ FAQ
http://www.parashift.com/c++-faq-lite/strange-inheritance.html#faq-23.5
Your derived type is not constructed yet.
Class Cat : Animal
{
//...
};
When you create a create a Cat object the following happens:
Construct Animal
Construct Cat
When your object goes out of scope or gets destroyed via delete if on the heap, the following happens:
Destruct Cat
Destruct Animal
For this reason you should not call virtual functions in your constructor or destructor. You would even have a pure virtual function call if you did not have an implementation in your base class.
You are going to have to:
GUIListbox lb;
lb.SetupCallbacks();
The point of virtual is so that you can do things like:
GuiWindow *lb = new GuiListbox();
lb->SetupCallback();//Gets correctly resolved to GuiListBox's version
The problem is that you are trying to call the virtual function form the constructor. The base class constructor is called before the constructor of the derived class, so the "derived parts" of the object are not created yet when the base classes constructor runs.
The object will behave like an object of the base class type until the base classes constructor is finished and the derived classes constructor starts. This means that calls to virtual functions will not call implementations defined in the derived class, they will just execute the version from the base class.
Also see the C++ FAQ lite for more details and possible workarounds.
The quick answer is that you may have to declare a constructor in GUIListbox which calls SetupCallbacks. The reason is more complicated: because GUIListbox doesn't declare a constructor, when you declare an object of that type the GUIWindow constructor is called. When the GUIWindow constructor is running, the object isn't a GUIListbox yet. From the compiler's perspective, it only becomes a GUIListbox once the (empty) constructor for that class starts. So when the first constructor runs, the methods from GUIWindow are called. IOWs, this doesn't work, and will never work in C++ the way that you want it to.
Here's a reference describing this pitfall in detail: http://www.artima.com/cppsource/nevercall.html.
And here's an explanation from my favorite C++ resource: http://yosefk.com/c++fqa/inheritance-mother.html#fqa-23.5