I'm a bit confused about how virtual base classes work. In particular, I was wondering how the constructor of the base class gets called. I wrote an example to understand it:
#include <cstdio>
#include <string>
using std::string;
struct A{
string s;
A() {}
A(string t): s(t) {}
};
struct B: virtual public A{
B(): A("B"){}
};
struct C: virtual public A {};
struct D: public B, public C {};
struct E: public C, public B {};
struct F: public B {};
int main(){
D d;
printf("\"%s\"\n",d.s.c_str());
E e;
printf("\"%s\"\n",e.s.c_str());
F f;
printf("\"%s\"\n",f.s.c_str());
B b;
printf("\"%s\"\n",b.s.c_str());
}
Which outputs
""
""
""
"B"
I wasn't sure what would happen in the first two cases, but for the third one at least I was expecting the output to be "B". So now I'm just confused. What are the rules for understanding how the constructor of A gets called?
Any non-virtual bases are then constructed before the derived class constructor is called. If a derived class has one virtual base class and other non-virtual base class, then the constructor of the virtual base class will be constructed first even though it appears at second position in the declaration.
Overview. Virtual base classes in C++ are used as a way of preventing multiple instances of a given class from appearing in an inheritance hierarchy when using multiple inheritances.
The virtual mechanism works only when we have a base class pointer to a derived class object. In C++, the constructor cannot be virtual, because when a constructor of a class is executed there is no virtual table in the memory, means no virtual pointer defined yet. So, the constructor should always be non-virtual.
You can call the base class constructor from the child class by using the super() which will execute the constructor of the base class. Example: Javascript.
There is always just one constructor call, and always of the actual, concrete class that you instantiate. It is your responsibility to endow each derived class with a constructor which calls the base classes' constructors if and as necessary, as you did in B
's constructor.
Update: Sorry for missing your main point! Thanks to ildjarn.
However, your B
inherits virtually from A
. According to the standard (10.1.4 in the FIDS), "for each distinct baseclass that is specified virtual, the most derived object shall contain a single base class subobject of that type". In your case this means that when constructing the base, your class F
immediately calls A
's default constructor, not B
's.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With