Virtual Constructor Idiom - Virtuous Or Complete Utter Fallacy - c++

One of the golden rules in C++ is that the life-time of an instance begins when its constructor completes successfully and ends when its destructor begins.
From this rule we conclude that it is NOT a good idea to call virtual methods in a constructor as the possible derived instance is not valid which would lead to undefined behavior.
The Virtual Constructor Idiom as mentioned in C++ FAQ 20.8 seems to indicate the contrary.
My question is:
What is the exact definition in the standard for defining the life time of objects relative to calls from their constructors and destructors?
and furthermore is the So called "Virtual Constructor Idom" valid?

I think you're confusing two separate (if vaguely related) things.
It is well-known that one shouldn't call virtual functions from constructors (directly or indirectly), for reasons discussed here.
What the FAQ is talking about is calling a constructor from a virtual function. In some sense it is the opposite of #1. The idea is to choose the constructor (i.e. the class) based on the dynamic type of some existing object.

An object exists as the type of the class the constructor belongs to when the constructor starts, the object just may be in an inconsistent state (which is fine, as execution is currently inside one of the object's methods). That is, an object that is actually of type Derived that inherits from Base is treated as a Base in Base constructors; this in any Base::Base() is treated as a Base *, no matter the actual type of the object that this points to. Calling virtual methods is fine. In a constructor, the virtual methods for the constructor's class will be called, rather than for the actual type of the object.
Your first question is covered in "Base class on the initialisation list of a derived class' copy constructor". The short answer is it's covered by § 12.7 2-3 of C++03.
The virtual constructor idiom is completely valid.

Related

Missed Optimization: std::vector<T>::pop_back() not qualifying destructor call?

In an std::vector<T> the vector owns the allocated storage and it constructs Ts and destructs Ts. Regardless of T's class hierarchy, std::vector<T> knows that it has only created a T and thus when .pop_back() is called it only has to destroy a T (not some derived class of T). Take the following code:
#include <vector>
struct Bar {
virtual ~Bar() noexcept = default;
};
struct FooOpen : Bar {
int a;
};
struct FooFinal final : Bar {
int a;
};
void popEm(std::vector<FooOpen>& v) {
v.pop_back();
}
void popEm(std::vector<FooFinal>& v) {
v.pop_back();
}
https://godbolt.org/z/G5ceGe6rq
The PopEm for FooFinal simply just reduces the vector's size by 1 (element). This makes sense. But PopEm for FooOpen calls the virtual destructor that the class got by extending Bar. Given that FooOpen is not final, if a normal delete fooOpen was called on a FooOpen* pointer, it would need to do the virtual destructor, but in the case of std::vector it knows that it only made a FooOpen and no derived class of it was constructed. Therefore, couldn't std::vector<FooOpen> treat the class as final and omit the call to the virtual destructor on the pop_back()?
Long story short - compiler doesn't have enough context information to deduce it https://godbolt.org/z/roq7sYdvT
Boring part:
The results are similar for all 3: msvc, clang, and gcc, so I guess the problem is general.
I analysed the libstdc++ code just to find pop_back() runs like this:
void pop_back() // a bit more convoluted but boils-down to this
{
--back;
back->~T();
}
Not any surprise. It's like in C++ textbooks. But it shows the problem - virtual call to a destructor from a pointer.
What we're looking for is the 'devirtualisation' technique described here: Is final used for optimisation in C++ - it states devirtualisation is 'as-if' behaviour, so it looks like it is open for optimisation if the compiler has enough information to do it.
My opinion:
I meddled with the code a little and i think optimisation doesn't happen because the compiler cannot deduce the only objects pointed by "back" are FooOpen instances. We - humans - know it because we analyse the entire class, and see the overall concept of storing the elements in a vector. We know the pointer must point to FooOpen instance only, but compiler fails to see it - it only sees a pointer which can point anywhere (vector allocates uninitialized chunk of memory and its interpretation is a part of vector's logic, also the pointer is modified outside the scope of pop_back()). Without knowing the entire concept of vector<> i don't think of how it can be deduced (without analysing the entire class) that it won't point to any descendant of FooOpen which can be defined in other translation units.
FooFinal doesn't have this problem because it already guarantees no other class can inherit from it so devirtualisation is safe for objects pointed by FooFinal* or FooFinal&.
Update
I made several findings which may be useful:
https://godbolt.org/z/3a1bvax4o), devirtualisation can occur for non-final classes as long as there is no pointer arithmetic involved.
https://godbolt.org/z/xTdshfK7v std::array performs devirtualisation on non-final classes. std::vector fails to do it even if it is constructed and destroyed in the same scope.
https://godbolt.org/z/GvoaKc9Kz devirtualisation can be enabled using wrapper.
https://godbolt.org/z/bTosvG658 destructor devirtualisation can be enabled with allocator. Bit hacky, but is transparent to the user. Briefly tested.
Yes, this is a missed optimisation.
Remember that a compiler is a software project, where features have to be written to exist. It may be that the relative overhead of virtual destruction in cases like this is low enough that adding this in hasn't been a priority for the gcc team so far.
It is an open-source project, so you could submit a patch that adds this in.
It feels a lot like § 11.4.7 (14) gives some insight into this. As of latest working draft (N4910 Post-Winter 2022 C++ working draft, Mar. 2022):
After executing the body of the destructor and destroying any objects with automatic storage duration
allocated within the body, a destructor for class X calls the destructors for X’s direct non-variant non-static data
members, the destructors for X’s non-virtual direct base classes and, if X is the most derived class (11.9.3), its
destructor calls the destructors for X’s virtual base classes. All destructors are called as if they were referenced
with a qualified name, that is, ignoring any possible virtual overriding destructors in more derived classes.
Bases and members are destroyed in the reverse order of the completion of their constructor (see 11.9.3).
[Note 4 : A return statement (8.7.4) in a destructor might not directly return to the caller; before transferring control
to the caller, the destructors for the members and bases are called. — end note]
Destructors for elements of an array are called in reverse order of their construction (see 11.9).
Also interesting for this topic, § 11.4.6, (17):
In an explicit destructor call, the destructor is specified by a ~ followed by a type-name or decltype-specifier
that denotes the destructor’s class type. The invocation of a destructor is subject to the usual rules for
member functions (11.4.2); that is, if the object is not of the destructor’s class type and not of a class derived
from the destructor’s class type (including when the destructor is invoked via a null pointer value), the program has undefined behavior.
So, as far as the standard cares, the invocation of a destructor is subject to the usual rules for member functions.
This, to me, sounds a lot like destructor calls do so much that compilers are likely unable to determine, at compile-time, that a destructor call does "nothing" - as it also calls destructors of members, and std::vector doesn't know this.

C++ Calling final virtual function in constructor

It's true that calling virtual function in constructor and destructor is not a good practice, and should be avoided. It's because virtual functions are affected by subclasses, but in constructing or destructing phase subclasses are not yet constructed(in constructing) or already destructed(in destructing).
However what happens if a virtual final function is invoked in constructor or destructor? I assume that there should be no problem, since it's not logically wrong.
Calling virtual function in constructor and destructor is forbidden because accessing to subclass' variable, not initialized yet, can occur in overridden version of virtual function, which is declared in the subclass.
While virtual final function is not, it's final and there's no way to access to subclass' variables.
But this is my assumption, and there could be any more reasons that calling virtual function in constructor or destructor is not reasonable.
So, in conclusion,
Is calling virtual final function in constructing/destructing phase is allowed in C++ standard?
If so, is it widely implemented to most C++ compilers?
If it's not, is there any reason for that?
Is calling virtual final function in constructing/destructing phase is
allowed in C++ standard?
Calling a virtual function during construction/destruction is well defined and completely legal except in the case of pure virtual functions.
Calling virtual function in constructor and destructor is forbidden
I don't know (nor cares) who says it's "bad" or "forbidden" from a stylistic point of view, code maintenance point of view... The ability to maintain code depends first on knowing the relevant language and tools well; not knowing what virtual calls do during these phases (*) will lead to misunderstand on the part of the maintainers which is fixed by selecting more experienced maintainers and not dumbing down the programming style.
(*) which aren't technically part of the "lifetime" of the object, which isn't even a very useful concept as objects are usable and used in their constructor (before their lifetime has started) in any non trivial program (I think the standard should simply suppress this unneeded concept).
accessing to subclass' variable, not initialized yet, can occur in
overridden version of virtual function, which is declared in the
subclass.
It can't. During construction of a base class subobject B (say by constructor B::B()), the type of the object is being constructed is by definition B.
overridden version of virtual function, which is declared in the
subclass.
No, there is no existing subclass object at that point, so there is no overriding.
While virtual final function is not, it's final and there's no way to
access to subclass' variables.
It makes no difference.
The dynamic type of a polymorphic object is established by a constructor, after the constructors for base classes and before constructing members.
If so, is it widely implemented to most C++ compilers?
In practice all compilers implement setting the dynamic type of an object by changing the one or many vtable pointers to point to appropriate vtables for the type; that is done as part of construction.
It means that during construction, the vptr value changes as derived objects are constructed.
First, the rule is: "Do not directly or indirectly invoke a virtual function from a constructor or destructor that attempts to call into the object under construction or destruction." That's not opinion. That's the SEI CERT coding standard. Original document at:
https://resources.sei.cmu.edu/downloads/secure-coding/assets/sei-cert-cpp-coding-standard-2016-v01.pdf
and a link to the relevant rule OOP50-CPP at:
https://wiki.sei.cmu.edu/confluence/display/cplusplus/OOP50-CPP.+Do+not+invoke+virtual+functions+from+constructors+or+destructors.
In answer to the original question, there are several exceptions to this rule. One of those, OOP50-CPP-EX2, is if the function or class is marked as final. Then it cannot be overridden by a derived class. You can also explicitly qualify the function call.
And yes, final is widely implemented.

C++ child constructor and VPTR

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.

Virtual constructors

I was wondering what is the meaning of a virtual constructor and how would it be used.
In addition I know that C++ does not allow for a virtual constructor, and I was wondering why.
C++ does not allow virtual constructors because you need an object to invoke a virtual method in the first place!
The term virtual constructor is used for for idiom and a well-known design pattern. This idiom/pattern involves the definition of factory: an intermediate object with a virtual method who's role is to create the object in question. Because the method is virtual and it's purpose is to create an object, it is nicknamed a "virtual constructor."
There are no virtual constructors in C++ though it is possible to simulate the behavior.
Why no virtual constructors in C++?
My attempt to give a Reasoning:
The standard states that the object creation is not complete until the closing brace of the constructor. Thus a object exists only after the constructor ends.
Virtual keyword is used to implement a polymorphic behavior, where in actual function to be called is evaluated at run time, depending on the actual type of object, this is pointing to. In order for the constructor to be dispatched using the virtual table mechanism, there has to be an completely existing object with a pointer to the virtual table, but inside a constructor the object construction itself is not complete so how can a pointer to the virtual table exist if the object isn't completely formed?
Reasoning of Dr. Bjarne Stroustrup:
Why don't we have virtual constructors?
Virtual constructor Fully Explained As the virtual constructor or any constructor is called automatically just after the creation of object or we can say it is the guaranteed first function that will run in the life-cycle of the object. Also Virtual function is needed when we are in the need of binding the base class pointer to derived class object and this is done through late binding which is achieved at runtime but the constructor is bond at compile time to confirm that there is need of creation of default constructor or not. Also, to late binding there is need of virtual pointer which is not created at compile time.

Constructors cannot be virtual, why? Not a dupe [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Why do we not have a virtual constructor?
I know this has been asked before but I didn't understand the complex technical words used in the other answers.
I read on a community the reason that constructors cannot be virtual is
The ‘virtual’ mechanism works on a logically complete (completely constructed) object. We know that we use constructors to logically initialize our objects. In other words, the object is not completely constructed until the constructor has finished executing. Thus, we can’t have virtual constructors.
There is a misconception that by then virtual table is incomplete so we can’t have virtual constructors. Just before the constructor starts executing the virtual table is properly constructed and the ‘this’ pointer passed to the constructors. Moreover, virtual table mechanism is implementation depended, and finds no place in the C++ standard. And hence, to argue over this issue using the virtual table concept is illogical.
Now, as the constructor finishes executing any other function can be virtual. Destructor is no exception to this rule as it is a function. Virtual destructors are required in case we use a base class pointer to refer to a derived class object, use it, and then delete it. If we have virtual destructor, using ‘delete’, a chain of destructors is called starting from the derived to the base. But, had there been no ‘virtual’ in destructor only the base class destructor is called (and not the derived). This (may) generate inconsistencies in the program.
Is the above reason correct? The answer doesn't talk about the static and dynamic types of objects.
Virtual constructors don't make sense and aren't necessary. The only time you call a constructor is when creating an object. You need to know the type of an object in order to create it, so the static and dynamic types are the same, and the correct constructor to call is the one for that type.
That's why they aren't necessary. Why they don't make sense, is that when creating an object, base class constructors are called as well as derived class constructors. If the base class constructor was overridden in the derived class, is that supposed to mean that the base class constructor isn't called after all?
Other languages have virtual constructors, perhaps because constructors in those languages are methods, and they only have virtual invocation for non-static methods. But those other languages (Java and Python spring to mind) have to introduce special rules that constructors must/should construct their base class explicitly as a call from the constructor. C++ just does it (perhaps in an initializer list, if the base class constructor requires parameters), using non-virtual constructors, and there is no option to enter the body of the constructor with uninitialized base class sub objects.
To quote from The C++ Programming Language:
To construct an object, a constructor
needs the exact type of the object it
is to create. Consequently, a
constructor cannot be virtual.
Furthermore, a constructor is not
quite an ordinary function. In
particular, it interacts with memory
management routines in ways ordinary
member functions don’t. Consequently,
you cannot have a pointer to a
constructor.
It must be interesting to note that C++ do have an idiom called virtual constructor. You can read more about that here.
Yes, the reason is you need to have a pointer/reference to a complete object already before you can call a virtual function. When the constructor is being invoked there's no complete object yet. Even more, when you do new SomeClass() you don't even have a pointer yet - the pointer is returned upon the new statement is completed successfully.
The virtual keyword cannot be applied to a constructor since a constructor turns raw bits into a living object, and until there is a living object against which to invoke a member function, the member function cannot possibly work correctly. Instead of thinking of constructors as normal member functions on the object, imagine that they are static member functions that create objects. - C++ FAQs