Virtual base class initialization - c++

Looking for an explanation of some fact in the standard I found this:
An abstract class (10.4) is never a most derived class, thus its
constructors never initialize virtual base classes, therefore the
corresponding mem-initializers may be omitted.
This is from the paragraph 12.6.2 of the final working draft. Since, It's embedded in Note and no example is provided, I don't know how it should be treated. So, I tried the example:
#include <iostream>
struct B{
~B(){}
B(){ std::cout << "B()" << std::endl; }
B(int){ std::cout << "B(int)" << std::endl; }
};
struct A : virtual B
{
int s;
virtual void foo() = 0;
A(int a) : B(a) { std::cout << "A(int)" << std::endl; }
};
struct D : A{
D() : A(10){ }
virtual void foo(){ }
} d;
int main()
{
}
and got the output
B()
A(int)
http://coliru.stacked-crooked.com/a/b16c68226f072ced
in spite of specifying the B's constructor in the ctor-initializer. Is that what they mean?

In this example, D is the most derived class and will construct B using the default (no parameter) constructor.
An abstract class is never most derived because you have to derive from it in order to instantiate it.

Related

Conditional call to base constructor

Currently, I have a based class with two different constructors:
class Base {
public:
Base(std::string filname){...}
Base(int a, int b) {...}
};
and a derived class of Base class. What I would like to do is to choose which constructor call inside the constructor of the derived class, but not in the initializer list. Something like this:
class Derived : public Base {
public:
Derived() {
if( /* exists("myFile") */ )
this->Base("myFile");
else
this->Base(1,2);
}
}
Is it possible to do that?, or because the base class is initialize before the derived class, the only way to call to the base constructor is in the initializer list?
Thanks
The choice of which base constructor is called happens before the body of the function and there's no way to change it at run time like that. However, you might be able to get close. If the base class also has a move constructor, or you could you add one, you could use that:
class Derived : public Base {
public:
Derived()
: Base{ exists("myFile") ? Base{"myFile"} : Base{1, 2} } {
}
}
This will call exists("myFile"); if that returns true, it will construct a temporary Base using the first constructor, and if it returns false it will construct a temporary Base using the second constructor. Either way, it will then construct the actual base subobject using this temporary.
You can simulate that by introducing a factory function:
class Base {
public:
Base(std::string filname);
Base(int a, int b);
};
class Derived : public Base {
Derived(std::string filname) : Base(filname) {}
Derived(int a, int b) : Base(a, b) {}
public:
static Derived create() {
if( /* exists("myFile") */ )
return Derived("myFile");
else
return Derived(1,2);
}
};
int main(){
auto d = Derived::create();
}
Alternatively, if derivation from Base is not required, an instance of Base can be held as a member (std::unique_ptr or std::aligned_storage) that you can initialise however you please.
Based on #DanielH comment in his answer I have developed an alternative solution which also works with abstract base classes in C++11:
#include <iostream>
struct Base {
Base(int x) {
std::cout << "Base x = " << x << std::endl;
}
Base() {
std::cout << "Base default" << std::endl;
}
virtual void foo() = 0;
};
struct Derived : Base {
struct TagA {};
struct TagB {};
Derived(bool condition)
: Derived(condition ? Derived{TagA()} : Derived{TagB()})
{}
void foo() override {}
private:
Derived(TagA dummy)
: Base(42)
{
std::cout << "Derived A dummy" << std::endl;
}
Derived(TagB dummy)
{
std::cout << "Derived B dummy" << std::endl;
}
};
int main() {
std::cout << "Construct Derived with false" << std::endl;
Derived x(false);
std::cout << "Construct Derived with true" << std::endl;
Derived y(true);
}

overriding virtual function from several base classes

Assuming I have code like this:
struct Base1 {
virtual void foo() = 0;
};
struct Base2 {
virtual void foo() = 0;
};
struct Derived : Base1, Base2 {
void foo() override {}
};
I am trying to produce a single override for several functions of different base classes with same name/signature.
Is such an overriding legal and well-defined in c++?
Is such an overriding legal and well-defined in c++?
Yes, it is perfectly legal and well defined as long as you override the virtual function in the derived class.
If you create an object of Derived structure and invoke the foo function it will invoke the overridden function.
The compiler will always search the called function from local to the global scope. So here compiler will check if foo is defined in the Derived scope if not found it will check in the Base scope and since you have provided the definition of foo in the derived scope the compiler won't check Base scope.
Try this code and you will get a better idea.
The output will be This is derived.
#include <iostream>
using namespace std;
struct Base1 {
virtual void foo() {
cout << "This is base1" << endl;
}
};
struct Base2 {
virtual void foo() {
cout << "This is base2" << endl;
}
};
struct Derived : Base1, Base2 {
void foo() {
cout << "This is derived" << endl;
}
};
int main() {
Derived d;
d.foo();
return 0;
}

Calling a member function of a derived class from the base class constructor

Suppose I have
struct C {
C() { init(); };
void init() { cout << "C" << endl; };
};
struct D : public C {
D() : C() { };
void init() { cout << "D" << endl; }
};
D();
why I get "C" printed? How can change this behaviour (and get "D").
How if I want both?
why I get "C" printed?
C::init() is not declared as virtual, so D cannot override it. But even if C::init() were declared as virtual, D::init() would still not be called when init() is called inside of C's constructor.
C++ constructs base classes before derived classes (and destructs derived clases before base classes). So C's constructor runs before D is constructed (and C's destructor runs after D is destructed). The VMT of the object being constructed/destructed simply does not point at D's method table when C is being constructed/destructed, it points at C's method table instead.
How can change this behaviour (and get "D").
You cannot call a derived virtual method from inside of a base class constructor/destructor. The VMT does not contain a pointer to the derived class method table at those stages.
You have a quite fundamental problem here: You want to call a member function of a derived class on an object that does not exist yet.
Remember that objects are constructed by first constructing the base sub-object and then the derived object. So even if you'd manage to apply a “clever” trick to actually invoke the derived class' init function, as soon as that function would try to access any data member of the derived object, it would cause arbitrary damage. On the other hand, it is fine to access only the base object, as long as you don't rely on any invariant that the constructor has not established yet. Therefore, if you don't need access to the derived object's data, you can make the init function static and pass it a reference to the base class object.
Maybe this is coming close to what you are trying to do.
#include <iostream>
struct Base
{
Base(void (*fp)(Base&) = Base::init) { fp(*this); }
static void init(Base&) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
};
struct Derived : Base
{
Derived() : Base(Derived::init) { }
static void init(Base&) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
};
int
main()
{
Base b {};
std::cout << std::endl;
Derived d {};
}
Output:
static void Base::init(Base&)
static void Derived::init(Base&)
Here, the base class constructor takes a function pointer to an initializer function that takes a reference to a Base object. The function defaults to Base::init but derived classes can replace it. Be aware, however, that in this design, the Base class constructor may not safely assume that any side effect of Base::init actually took place. It is fine as an extension mechanism (if Base::init does nothing or is disposable), though.
But I doubt that you need to use this kind of machinery. If all you want to do – and this should be the normal case – is to first initialize the base object and then the derived object, C++ already will do the right thing by default if you simply call the functions from the respective constructors.
struct Base
{
Base() { this->init(); }
void init() { std::cout << __PRETTY_FUNCTION__ << std::endl; }
};
struct Derived : Base
{
Derived() { this->init(); }
void init() { std::cout << __PRETTY_FUNCTION__ << std::endl; }
};
// main() as above ...
Output:
void Base::init()
void Base::init()
void Derived::init()
And if we only want to call the most derived class' init function, we can simply tell the base class not to run its own.
struct Base
{
Base(const bool initialize = true) { if (initialize) this->init(); }
void init() { std::cout << __PRETTY_FUNCTION__ << std::endl; }
};
struct Derived : Base
{
Derived() : Base(false) { this->init(); }
void init() { std::cout << __PRETTY_FUNCTION__ << std::endl; }
};
// main() as above ...
Output:
void Base::init()
void Derived::init()
You only can remove init() from C constructor to not print "C".
To also print "D" add init() in D() constructor.
If for some cases you want print "C" or "D" and in some don't do something like this
struct C {
C() { };
void init() { cout << "C" << endl; };
};
struct D : public C {
D() : C()
{
if(some condition)
C::init();
if(some condition)
init();
};
void init() { cout << "D" << endl; }
};
D();

Polymorphism with 3 classes in C++

The following code prints 1 2, but I would expect it to print 1 1.
#include <iostream>
using namespace std;
class A {
public:
virtual void f() { cout << "0" << endl; }
};
class B : public A{
public:
void f() { cout << "1" << endl; }
};
class C : public B{
public:
void f() { cout << "2" << endl; }
};
int main() {
A *pa = new B();
B *pb = new C();
pa->f();
pb->f();
}
In my understanding, pa->f() executes B's f() function since A's is virtual, but why does pb->f() execute C's f() function when B's f() is not virtual.
Additionally, if I remove 'virtual' from class A, it prints 0 1, which makes sense because A and B execute their own f() functions since they aren't virtual. How come pb->f() changes if it isn't affected since it's only A that changes?
but why does pb->f() execute C's f() function when B's f() is not virtual.
Because the dynamic type of pb is C and C::f is indeed virtual. When you declare
virtual void f();
in the base class, every other void f() of the derived classes in the hierarchy is also virtual, as per §10.3/2:
If a virtual member function vf is declared in a class Base and in a class Derived, derived directly or indirectly from Base, a member function vf with the same name, parameter-type-list (8.3.5), cv-qualification, and ref- qualifier (or absence of same) as Base::vf is declared, then Derived::vf is also virtual (whether or not it is so declared) and it overrides112 Base::vf.
(emphasis mine)
In fact:
class A {
public:
virtual void f() { cout << "0" << endl; }
};
class B : public A{
public:
virtual void f() { cout << "1" << endl; }
};
class C : public B{
public:
virtual void f() { cout << "2" << endl; }
};
is equivalent to your code. It just so happens that the C++ standard allows virtual to be omitted in those cases.
It happens because writing virtual keyword in subclasses is not necessary, it just improves readability.

Does derived class' member functions inherit virtualness from base class?

Say we have the following two classes, A is the base class with virtual destructor and B is the derived class whose destructor doesn't have 'virtual' qualifier. My question is, if I going to derive more classes from B, will B's destructor automatically inherit the virtualness or I need to explicitly put 'virtual' before '~B() {...}'
class A
{
public:
A() { std::cout << "create A" << std::endl;};
virtual ~A() { std::cout << "destroy A" << std::endl;};
};
class B: A
{
public:
B() { std::cout << "create B" << std::endl;};
~B() { std::cout << "destroy B" << std::endl;};
};
From C++ standard (section 10.3):
If a virtual member function vf is declared in a class Base and in
a class Derived, derived directly or indirectly from Base, [...]
then Derived::vf is also virtual (whether or not it is so declared).
So yes.
If base class method is virtual then all the subsequent derived class methods will become virtual. However, IMO it's a good programming practice to put virtual ahead of the method; just to indicate the reader the nature of the function.
Also note that there are some corner case where you might get unexpected results:
struct A {
virtual void foo(int i, float f) {}
};
sturct B : A {
void foo(int i, int f) {}
};
Here actually, B::foo() is not overriding A::foo() with virtual mechanism; rather it's hiding it. So irrespective of you make B::foo() virtual, there is no advantage.
In C++0x, you have override keyword, which overcomes such problems.
Virtualness is inherited all the way down. You only need to specify it in the top base class.
This is true for destructors as well as normal member functions.
Example:
class Base { virtual void foo() { std::cout << "Base\n"; } };
class Derived1 : public Base { void foo() { std::cout << "Derived1\n"; } };
class Dervied2 : public Derived1 { void foo() { std::cout << "Derived2\n"; } };
int main()
{
Base* b = new Base;
Base* d1 = new Derived1;
Base* d2 = new Derived2;
Derived1* d3 = new Derived2;
b->foo(); // Base
d1->foo(); // Derived1
d2->foo(); // Derived2
d3->foo(); // Derived2
}
or I need to explicitly put 'virtual' before '~B() {...}'
No, you need not, although you can put virtual here to make code more clear for the reader. This applies not only for destructors but for all member functions.