class A {
int i;
public:
A() {cout<<"in A's def const\n";};
A(int k) {cout<<"In A const\n"; i = k; }
};
class B : virtual public A {
public:
B(){cout<<"in B's def const\n";};
B(int i) : A(i) {cout<<"in B const\n";}
};
class C : public B {
public:
C() {cout<<"in C def cstr\n";}
C(int i) : B(i) {cout<<"in C const\n";}
};
int main()
{
C c(2);
return 0;
}
The output in this case is
in A's def const
in B const
in C const
Why is this not entering into in A const
`It should follow the order of 1 arg constructor call.
But what actually is happening on deriving B from A using virtual keyword.
There are few more question
Even if I remove the virtual keyword in above program and remove all the default constructor it gives error. So, why it needs the def constructor
The constructors for virtual base classes are always called from the most derived class, using any arguments it might pass in. In your case, the most derived class doesn't specify an initializer for A, so the default constructor is used.
As JamesKanze has explained, in case of virtual inheritance it is the most derived class that calls the virtual base class' constructor. So, if you want A's constructor that takes an integer to be called, you need to add that to C's initialization list.
C(int i) : A(i), B(i) {cout<<"in C const\n";}
For the second part of your question, default constructors are not required, but then the derived class must call the non-default constructor explicitly, since the compiler is unable to do that for you in the absence of a non-default constructor.
#include <iostream>
using namespace std;
class A {
int i;
public:
// A() {cout<<"in A's def const\n";};
A(int k) {cout<<"In A const\n"; i = k; }
};
class B : virtual public A {
public:
// B(){cout<<"in B's def const\n";};
B(int i) : A(i) {cout<<"in B const\n";}
};
class C : public B {
public:
C() : A(42), B(42) {cout<<"in C def cstr\n";}
C(int i) : A(i), B(i) {cout<<"in C const\n";}
};
int main()
{
C c(2), c2;
return 0;
}
This prints out
In A const
in B const
in C const
In A const
in B const
in C def cstr
There are two questions here.
Why is this not entering into in A const?
Because you are using virtual inheritance.
When you use virtual inheritance, the Initialization list of most-derived-class's ctor directly invokes the virtual base class's ctor.. In this case, that means that C's constructor calls A's constructor directly. Since you have not specified which A constructor to call in C's initialization list, the default constructor is called.
This is fixed by changing your implementation of C::C(int) to:
C(int i) : A(i), B(i) {cout<<"in C const\n";}
If I remove the virtual keyword in above program and remove all the
default constructor it gives error. So, why it needs the def
constructor?
Because B also doesn't specify which A ctor to call, so the default constructor is used. If you remove As def ctor, B can't be compiled.
Related
Is possible to have virtual inheritance for class not providing default constructor?
The present diamond diagram (the simplest one with the only change of no default constructor provided) does not compile (g++ 4.4.3).
class A {
public:
A(int ) {}
};
class B : virtual public A {
public:
B(int i) : A(i) {}
};
class C : virtual public A {
public:
C(int i) : A(i) {}
};
class D : public B, public C {
public:
D(int i) : B(i), C(i) {}
};
Thanks,
Francesco
You need to call A's constructor explicitly here
D(int i) : A(i), B(i), C(i) {}
virtual base classes are special in that they are initialized by the most derived class and not by any intermediate base classes that inherits from the virtual base. Which of the potential multiple initializers would the correct choice for initializing the one base?
If the most derived class being constructed does not list it in its member initalization list then the virtual base class is initialized with its default constructor which must exist and be accessible.
Shamelessly copied from here :-)
I believe your class D also needs to explicitly call A's constructor in its initializer list.
The Dr. Dobbs article Multiple Inheritance Considered Useful explains various ways of dealing with this. The recommendation is basically to provide default constructors and init() methods. It adds more work for B and C but prevents D from having to know about A.
you need explict call A's construct like this:
D(int i) : A(i), B(i), C(i) {}
#include<iostream>
using namespace std;
class A {
int i;
public:
// A() {cout<<"in A's def const\n";};
A(int k) {cout<<"In A const\n"; i = k; }
};
class B : public A {
public:
//B(){cout<<"in B's def const\n";};
B(int i) : A(i) {cout<<"in B const\n";}
};
class C : public B {
public:
C() {cout<<"in C def cstr\n";}
C(int i) : B(i) {cout<<"in C const\n";}
};
int main()
{
C obj=new C(2);
return 0;
}
when i am running this code it shows
In constructor 'C::C()':
88c8237e3ffce7819f082b210069fd59.cpp:19:13: error: no matching function for call to 'B::B()'
why this happens as i am only caling parameterized constructors explicitly everywhere.??please help
C() {cout<<"in C def cstr\n";}
You cannot declare
C() {cout<<"in C def cstr\n";}
Because neither of the base classes A nor B have default (non-parameterized) constructors. If you uncommented those out your code would compile (except for the comment below).
Side comment, this is not correct
C obj=new C(2);
You could use any of the following
C obj(2);
C obj{2};
C obj = C(2);
But with new you'd have to assign to a pointer (which I wouldn't recommend unless you need heap allocated objects for some reason, in which case prefer smart pointers).
C* obj = new C(2);
delete obj; // remember to delete it when you're done
This question already has an answer here:
Why is Default constructor called in virtual inheritance?
(1 answer)
Closed 9 years ago.
C++11 standard provides a way to inherit constructors from the base class. My question is regarding earlier standards. Suppose I inherit constructors in the following way:
class Base {
public:
Base() {};
Base(int b) { a = ++b;}
virtual int foo() {return 0;}
int a;
};
class A : public virtual Base {
public:
A() {}
A(int b): Base(b) {}
int foo() {return a*a;}
};
class C : public A {
public:
C() {}
C(int b ): A(b) {}
int foo() { return (a*a + a);}
};
Note that I am having virtual inheritance of the Base class. Now when I try to initialize a pointer to an object of type C then instead of calling Base(b) constructor, the code ends up calling Base() constructor. Here is the main function that I used:
int main(){
C *c = new C(5);
std::cout << c->Base::a << std::endl;
}
The output value of "a" is 0. However, when I remove the virtual keyword while inheriting the Base class, then Base(b) constructor is called and the value of "a" is 6. Can someone help me in understanding what is going on? Why is it that with virtual inheritance default constructor is called?
Virtual base classes are initialised based on the member initialiser list of the constructor of the most derived class.
In your case, when you're creating an instance of C, its Base subobject will be initialised based on the member-initialiser list in C's constructor; and since Base is not listed there, it will be default-initialised.
If you were creating an instance of A, then indeed A's member-initialiser list would be used.
So to call the Base constructor which you want, you'd have to modify C's constructor like this:
C(int b ): A(b), Base(b) {}
I'm having a tricky time with calling rules for constructors in a type hierarchy. Here is what I do:
class A{
protected:
int _i;
public:
A(){i = 0;}
A(int i) : _i(i){}
virtual ~A(){}
virtual void print(){std::cout<<i<<std::endl;}
};
class B : virtual public A{
protected:
int _j;
public:
B() : A(){_j = 0;}
B(int i, int j) : A(i), _j(j){}
virtual ~B(){}
virtual void print(){std::cout<<i<<", "<<j<<std::endl;}
};
class C : virtual public B{
protected:
int _k;
public:
C() : B(){_k = 0;}
C(int i, int j, int k} : B(i,j), _k(k){}
virtual ~C(){}
virtual void print(){std::cout<<i<<", "<<j<<", "<<k<<std::endl;}
};
int main(){
C* myC = new C(1,2,3);
myC->print();
delete myC;
return 0;
}
Now, I would like to have new C(1,2,3) call the constructor of B(1,2) which then in turn should call the constructor A(1) to store _i=1, _j=2, _k=3. When creating the instance myC of the class C, for some reason I don't understand, however, the first constructor to be called is the standard constructor of A, i.e., A::A(); This obviously leads to wrong results, as the protected variable _i is assigned the value 0. The constructor A(1) is never called. Why is this so? I find this very counter intuitive. Is there some way to avoid explicitly calling all constructors within the type-hierarchy to achieve the desired behavior?
Thx for the help!
do you really need a virtual inheritance here?
you've got a problem because a very first virtual base ctor will be called first, but you don't specify any when inherit C from B (latter already have A virtually inherited, so default was called).
one solution is to remove virtual inheritance... as mentioned in the answer of Arne Mertz.
another (if you really want virtual inheritance) is to call A explicitly from C ctor:
C(int i, int j, int k} : A(i), B(i,j), _k(k){}
When you use virtual inheritance, the most derived class must call the constructors for all its virtual bases directly. In this case, the constructor for C must call the constructors for B and A. Since you only call the B constructor, it uses the default A constructor. It does not matter that the B constructor calls another A constructor: since it is a virtual base class, this call is ignored.
You have two ways around this problem: explicitly call the A(int) constructor:
C(int i, int j, int k} : A (i), B(i,j), _k(k){}
or use normal inheritance instead of virtual.
This is because you used virtual inheritance, which makes only sense in the presence of multiple inheritances. Just inherit normally, and all will be as you expect it.
Why do you declare virtual inheritance? If you remove virtual keyword from class B: virtual public A { ... then your code will work fine. By declaring virtual A, C will call A() directly. If you remove virtual then C will not call A().
class A {
int i;
public:
A() {cout<<"in A's def const\n";};
A(int k) {cout<<"In A const\n"; i = k; }
};
class B : virtual public A {
public:
B(){cout<<"in B's def const\n";};
B(int i) : A(i) {cout<<"in B const\n";}
};
class C : public B {
public:
C() {cout<<"in C def cstr\n";}
C(int i) : B(i) {cout<<"in C const\n";}
};
int main()
{
C c(2);
return 0;
}
The output in this case is
in A's def const
in B const
in C const
Why is this not entering into in A const
`It should follow the order of 1 arg constructor call.
But what actually is happening on deriving B from A using virtual keyword.
There are few more question
Even if I remove the virtual keyword in above program and remove all the default constructor it gives error. So, why it needs the def constructor
The constructors for virtual base classes are always called from the most derived class, using any arguments it might pass in. In your case, the most derived class doesn't specify an initializer for A, so the default constructor is used.
As JamesKanze has explained, in case of virtual inheritance it is the most derived class that calls the virtual base class' constructor. So, if you want A's constructor that takes an integer to be called, you need to add that to C's initialization list.
C(int i) : A(i), B(i) {cout<<"in C const\n";}
For the second part of your question, default constructors are not required, but then the derived class must call the non-default constructor explicitly, since the compiler is unable to do that for you in the absence of a non-default constructor.
#include <iostream>
using namespace std;
class A {
int i;
public:
// A() {cout<<"in A's def const\n";};
A(int k) {cout<<"In A const\n"; i = k; }
};
class B : virtual public A {
public:
// B(){cout<<"in B's def const\n";};
B(int i) : A(i) {cout<<"in B const\n";}
};
class C : public B {
public:
C() : A(42), B(42) {cout<<"in C def cstr\n";}
C(int i) : A(i), B(i) {cout<<"in C const\n";}
};
int main()
{
C c(2), c2;
return 0;
}
This prints out
In A const
in B const
in C const
In A const
in B const
in C def cstr
There are two questions here.
Why is this not entering into in A const?
Because you are using virtual inheritance.
When you use virtual inheritance, the Initialization list of most-derived-class's ctor directly invokes the virtual base class's ctor.. In this case, that means that C's constructor calls A's constructor directly. Since you have not specified which A constructor to call in C's initialization list, the default constructor is called.
This is fixed by changing your implementation of C::C(int) to:
C(int i) : A(i), B(i) {cout<<"in C const\n";}
If I remove the virtual keyword in above program and remove all the
default constructor it gives error. So, why it needs the def
constructor?
Because B also doesn't specify which A ctor to call, so the default constructor is used. If you remove As def ctor, B can't be compiled.