Regarding this post:
For implementations that use vtable, the answer is: Yes, usually. You
might think that vtable isn't required for abstract classes because
the derived class will have its own vtable, but it is needed during
construction: While the base class is being constructed, it sets the
vtable pointer to its own vtable. Later when the derived class
constructor is entered, it will use its own vtable instead.
I'm assuming the answer is correct, but I don't quite get it. Why is the vtable needed exactly for construction?
Because the standard says so.
[class.cdtor]/4
When a virtual function is called directly or indirectly from a
constructor or from a destructor, including during the construction or
destruction of the class's non-static data members, and the object to
which the call applies is the object (call it x) under construction or
destruction, the function called is the final overrider in the
constructor's or destructor's class and not one overriding it in a
more-derived class.
The rationale is that first the base class is constructed, then the derived one. If a virtual function is called inside the base class' constructor, it would be bad to call the derived class, since the derived class isn't initialized yet.
Remember that an abstract class may have non-pure virtual functions. Also, for debugging purposes, it is good to point pure virtual functions to a debugging trap (e.g. MSVC calls _purecall()).
If all virtual functions are pure, in MSVC you can omit the vtable with __declspec(novtable). If you use a lot of interface classes, this can lead to significant savings because you omit vfptr initialization. But if you accidentally call a pure virtual function, you'll get a hard to debug access violation.
vtables are implementation issues in C++, they are not part of the standard.
vtables are used for both dynamic dispatching of methods and for RTTI. While a nullptr vtable pointer would work for dynamic dispatching (as the vtable pointer is only used when you have an instance of that type) in a pure-abstract class, a dynamic_cast to a pure abstract class is legal, and it may require that the vtable itself exist.
Designers of the C++ implementation and ABI might have simply given the purely abstract class (a class with no implemented methods, just =0 ones) a vtable to make their implementation simpler. Every class has a vtable, and the vtable pointer gets set during construction of that class. Code can then rely on the fact that the vtable pointer exists and does not have to check for null every time. Code doesn't have to ask questions like "is this a purely abstract class".
For a non-pure abstract class (where some methods have implementations but some are pure virtual), during construction/destruction you can have defined (if unexpected) behavior that involves invoking exactly this class's version of a given method, and not the base class method or an inherited method. For this to work, you need to have a vtable set up. With a pure abstract class, there is no defined result of such a call, so the vtable is redundant, but for an abstract class that isn't totally abstract this does not hold.
When your class has a pure virtual function, that does not mean you cannot also have an implementation for it (!!). So that implies you can have an abstract class, which is also fully implemented. The constructor of your abstract class has to be able to call all functions - even the pure virtual ones, because of this point - that exist for it so far.
If you'd have substituted the client one, you'd get different behaviour for the base class constructor depending on the deriving class - not a great idea, so that's not allowed. You could put in place no vtable and statically resolve all function calls - that works, but it implies handling the constructor specially compared to all other functions and requires inlining all other functions to do this (since a function called from the constructor may also call a virtual etc.) - not very practical.
So it just implements a vtable for the constructor and destructor to use during construction and destruction. It allows you to use typeid and dynamic_cast in the c'tor and d'tor with the predictable result and get reliable behaviour out of the virtual functions you have. No alternative solution would do that.
Related
I' ve read some articles, and as they say, main virtual destructor use cases are:
derived classes may have dynamic data allocation from heap, i.e. "own" that data object. So, they need some deletion routine in destructor. Deletion through base class pointer requires virtual declaration of destructors in all derived class till those with dynamic data allocation (base class also requires it)
this class has virtual methods. But this is unclear for me. Just calling virtual methods through base class pointer always results in the-most-derived-realization calls. They only exclusion for that rule is construction phase. Literaly, during it this object is not a derived type yet, even if later will be. Ok, what about destruction phase? As I understood, the rule is in the backward order. No matter, was destructor of some class in hierarchy declared as virtual, during each destructor this pointer is used as if of this class type, any derived were already been destroyed due to virtual d-r, or not destroyed (and that hypothetically may be ok in some design). Maybe this is the case, why d-r must be virtual? Vtable will have entries for derived class, and calling virtual methods in some base class from d-r will result in UB? Ok, but this rule applies only to case when this class calls some virtual methods in d-r, and they do have realization in derived classes.
My opinion, that there is also may be a case with no dynamic data allocation, no virtual methods in all hierarchy, but still derived destructors may do some critical tasks upon deletion (syncs, unlocks and so on). And we need virtual d-r in base class. May be such cases are results of bad design.
But anyway, developer of some public class cannot 100% know, if derived class will or not use some virtual methods in d-r, or allocate dynamic data. So, am I correct to say, that any public class, not declared as final, has to declare d-r as virtual? Only final keyword guarantees that any pointer to this class will always be of this type, and so, could be safely deleted non-virtually.
If a derived object is deleted through a pointer to the base class, then (and only then) the base class destructor must be virtual. Otherwise it is undefined behaviour. There are no other relevant rules.
If the class had a virtual function anyway, then no overhead is introduced. If the class did not have any other virtual functions, then the base class designer has to consider the trade between adding the runtime penalty of a virtual destructor, vs. the risk that a user of the class might try to delete a derived object through the base class pointer.
Here is a link to a similar discussion, with Standard quotes
In many sources, books etc. are written "don't call this->virtualFunction in child class constructor" and in some sources explain why you mustn't do it. Because at the moment of construction class isn't created at all. So virtual function that will be called from child constructor will be function of base class. It means that in child constructor body VPTR of that class pointed to base VTABLE.
So my question is,
what is the moment in object construction when VPTR of child class will be overriden to address on it's virtual table? I guess that some automatically generated code do it at end of constructor body or after constructor body will be executed.
And second question is,
why is VPTR overriden at the end of construction? Maybe for it have some important reasons?
Why can't override VPTR at beginning constructor body or after base class constructed?
Child::Child() :
Base()
//<----- Why not here?
//members initialization
{
//<----- Why not here?
//code
}
In many sources, books etc. are written "don't call this->virtualFunction in child class constructor"
I doubt that. It's often advised not to call virtual functions from the base class constructor, to avoid confusion if you expect them to call the final overrides, not the base-class versions. And you must certainly not call them from the base class if they are pure virtual there - that gives undefined behaviour.
Within the derived class constructor, they are well-defined and do what you would expect.
So virtual function that will be called from child constructor will be function of base class.
No, during the child's constructor body, the dynamic type is Child, and virtual functions calls will use the Child overrides.
what is the moment in object construction when VPTR of child class will be overriden to address on it's virtual table?
After all base class constructors have completed, and before child class members are initialised. Child member functions, including virtual functions, can be called from member initialisers (but not base class initialisers) or the constructor body.
You need to be careful calling them from member initialisers, since they might access uninitialised members. But within the constructor body, all base objects and members are initialised, so they are quite safe.
why is VPTR overriden at the end of construction?
It isn't. It happens at the first point you indicate with <----- Why not here?.
I disagree with your overly simplified reason to why you shouldn't call a virtual function. First of all, a VTABLE is not actually defined by the C++ standard, and is, in fact, implementation specific:
When is VTable in C++ created?
Calling a virtual function from a constructor is allowed by the standard, and should actually should call correctly within the hirearchy at that level (with some limitations)
C++ constructors: why is this virtual function call not safe?
http://www.parashift.com/c%2B%2B-faq-lite/calling-virtuals-from-ctors.html
However, there are many, many reasons not to do this.
The constructor for the derived class has not been called yet. Any access of any members of the derived class will yield undefined behavior.
There is a rule of thumb that you should keep constructors as simple and dumb as possible. This is due to the fact that error handling in constructors can be a giant pain due to destructor not being called and the only way to return a sensical error state is to throw an exception.
This will often break the dependency inversion principal, and may cross the line of demeter, and will usually introduce high coupling to the code.
Following this question, I'm wondering why a struct\class in C++ has to have a virtual method in order to be polymorphic.
Forcing a virtual destructor makes sense, but if there's no destructor at all, why is it mandatory to have a virtual method?
Because the type of a polymorphic object in C++ is, basically, determined from the pointer to its vtable, which is the table of virtual functions. The vtable is, however, only created if there's at least one virtual method. Why? Because in C++, you never get what you didn't explicitly ask for. They call it "you don't have to pay for something you don't need". Don't need polymorphism? You just saved a vtable.
Forcing a virtual destructor makes sense
Exactly. To destruct a virtual class manually (via delete) through its base class you need a virtual destructor. (Now, as I’ve been reminded in the comments, this isn’t usually needed: rather than use manual memory management, one would rely on modern smart pointers which also work correctly with non-virtual destructors.)
So any class which acts as a polymorphic base class usually needs either a virtual destructor or virtual functions anyway.
And since having runtime polymorphism adds an overhead (the class needs to store an additional pointer to its virtual method table), the default is not to add it, unless necessary anyway: C++’ design philosophy is “you only pay for what you need”. Making every class have a virtual method table would run afoul of this principle.
Because it is defined as such in the standard.
From 10.3/1 [class.virtual]
Virtual functions support dynamic binding and object-oriented programming. A class that declares or inherits a virtual function is called a polymorphic class.
It makes sense that if you use inheritance, then you have at least one virtual method. If you don't have any virtual method, then you could use composition instead.
polymorphism is to allow your subclasses to override the default behaviour of base class functions, so unless you have virtual methods in your base class, you can't override methods in base.
I'm wondering why does a struct\class in C++ has to have a virtual method in order to be polymorphic?
Because that is what polymorphic class means.
In C++, runtime polymorphism is achieved through virtual functions. A base class declares some virtual functions which the many derived classes implement, and the clients use pointers (or references) of static type of base class, and can make them point to objects of derived classes (often different derived classes), and then later on, call the implementation of derived classes through the base pointers. That is how runtime polymorphism is achieved. And since the central role is played by the functions being virtual, which enables runtime polymorphism, that is why classes having virtual functions is called polymorphic class.
Without any virtual method, there is no need to maintain a virtual pointer (abbreviated as vptr) for every object of the class. The virtual pointer is a mechanism for resolving virtual method calls at runtime; depending on the object's class, it might point to different virtual method tables (abbreviated as vtable) that contain the actual adresses of virtual methods.
So by checking to what vtable does the vptr point to, compiler can determine object's class, for example in dynamic_cast. Object without the vptr cannot have its type determined this way and is not polymorphic.
A C++ design philosophy is that "you don't pay for what you don't use". You might already know that a virtual function incur some overhead as a class has to maintain a pointer to its implementation. In fact, an object contains a reference to a table of function pointers called the vtable.
Consider the following example:
class Base
{
public:
virtual f() { /* do something */ }
};
class Derived : public Base
{
public:
virtual f() { /* do something */ }
};
Base* a = new Derived;
a->f(); // calls Derived::f()
Note that the variable a points to a Derived object. As f() is declared virtual the vtable of a will contain a pointer to Derived::f() and that implementation is executed. If f() is not virtual, the vtable will be empty. So Base::f() is executed as the type of a is Base.
A destructor behaves just like other member functions. If the destructor is not virtual, only the destructor in the Base class will be called. This might lead to memory/resource leaks if the Derived class implements RAII. If a class is intended to be sub-classed, its destructor should be virtual.
In some languages like Java all methods are virtual. So even objects that are not intended to be polymorphic will consume memory for maintaining the function pointers. In other words, you are forced to pay for what you don't use.
Classes only need virtual methods in order to be dynamically polymorphic - for the reasons described by others. You can still have static polymorphism through templates, though.
I've got a scenario where I'm writing somewhat deep object oriented code, with multiple layers of abstract base classes, and I'm wondering if I have to explicitly declare a destructor for each one.
Will the compiler generate a default one that's already virtual, or will I have to tell it to?
The default destructor is not virtual. If you declare the destructor of your base class as virtual, the destructors of the subclasses will be overrides, and thus also be virtual even without explicitly declaring them to be.
The GNU GCC compiler even gives a warning if you have a class hierarchy and your base class does not declare the destructor to be virtual because you most likely want it to be.
The answer is no. The only relevant requirement here is that classes with a vtable (i.e., with at least one virtual function) must have at least one a virtual destructor somewhere in their inheritance chain. Typically this means that your fundamental base class will provide an empty virtual destructor.
In general if some function is declared virtual in base class, there is no need to explicitly declare it virtual in subclasses. However it is good practice.
Declaring destructors in subclasses as virtual explicitly doesn't give you any serious advantages, so if you don't wont to write one more virtual, don't do that.
Does a pure-virtual object have a pointer to the vtbl?
(that probably points to NULL?)
thanks, i'm a little bit confused with all the virtual mechanism.
Don't worry about it. Virtual tables are an implementation detail, and aren't even guaranteed to exist. The more you worry about how it might be done, the less you learn about the actual language.
That said, yes. A concrete class will then set that pointer to point to the correct virtual table.
There isn't technically such a thing as a 'pure-virtual object'. I assume you mean an object with pure-virtual methods? But you can't actually create such an object because it would be abstract and the compiler would complain.
Having said that, while the object is being constructed it is briefly an instance of the abstract class before becoming an instance of the derived class. It will in such a case have a virtual table set the functions it defines. It will probably have NULL for the pure virtual methods. If you try calling that the program will crash.
You can try this out by calling virtual methods in the constructor. You'll find they invoke the base class version if you call the methods in the base class. If you call a pure virtual method it'll crash. (In some cases the compiler will figure out what you are doing and complain instead).
The take home is:
Don't call virtual functions in your constructor, its just likely to be confusing. In fact, in most cases it is best if your constructor just sets its internal status up and does not do anything too complicated.