#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
Related
I'm learning C++ OOP. I don't understand a principle, and I don't know what to google to find an answer.
If I have this:
#include <iostream>
class A
{
public:
int a;
A() : a(1){}
};
class B : virtual public A
{
public:
B() {this->a = 2;}
};
class C : virtual public A
{
public:
C() {this->a = 3;}
};
class D : public B, public C
{
public:
D() {this->a = B::a;}
};
int main()
{
D test;
std::cout << test.a << std::endl;
}
I expect the output to be 2 since I want the value of the inherited B class in the D class. It seems to me like the value of the C class is taken, because that constructor gets called last and overwrites the B::a value, is that right?
How would I go about getting values from the B class inside the D class?
The code below gives a compile-time error but when I remove the keyword "virtual" from below it works fine. I know that virtual inheritance is done to avoid multiple copies of base class members, but what is the significance of the keyword "virtual" here??
#include<iostream>
using namespace std;
class A {
int a;
A() {
cout<<"I am A\n";
a = 1;
}
public :
friend class B;
};
class B : virtual public A {
int b;
public :
B() {
cout<<"I am B\n";
b = 2;
}
};
class C : public B {
int c;
public :
C() {
cout<<"I am C\n";
c = 3;
}
};
int main()
{
C var;
return 0;
}
Initializaion of virtual base classes follows different logic than regular base classes.
From https://en.cppreference.com/w/cpp/language/derived_class#Virtual_base_classes:
All virtual base subobjects are initialized before any non-virtual base subobject, so only the most derived class calls the constructors of the virtual bases in its member initializer list:
In your case, the constructor of C can be thought of as:
C() : A(), B() {
cout<<"I am C\n";
c = 3;
}
That is a problem since A() is declared private.
When A is a regular base class of B, C() can be thought of as:
C() : B() { // No A()
cout<<"I am C\n";
c = 3;
}
That is not a problem given your posted code.
In Primer c++ 5th
class A {
public:
A() : a(1) {}
virtual ~A() = default;
private:
int a;
};
class B : public A {
public:
B() : b(2) {}
private:
int b;
};
class C : public B {
public:
C() : c(3) {}
private:
int c;
};
//class D : public B, public A { cause error
// public:
// D() : d(4) {}
// private:
// int d;
//};
int main()
{
//A *pa = new C;
//B *pb = dynamic_cast<B*>(pa); //1st case
B *pb = new B;
C *pc = dynamic_cast<C*>(pb); //2nd case
cout << pc << endl;
//A *pa = new D;
//B *pb = dynamic_cast<B*>(pa); //3rd case
}
//output: 0 cast failure
Q1:
Here in the above code .I can understand why the 2nd case doesn't work, but
the type of pb-pointed object is B which is the public base class of C .And this is the 2nd situation of what's said in Primer c++.
So why the 2nd case doesn't work while primer c++ said this kind of cast will succeed?
Q2:
the 3rd case. Errors occurred during compilation
error: āAā is an ambiguous base of āDā
What does this error mean?
in your second example you create a class B, B is a base class for C.
so you can't cast a base class to some derived class.
this will work:
B *pb = new C();
C *pc = dynamic_cast<C*>(pb);
regarding 3rd example D derive from B and A, but B also derive from A, this make problems for compiler. you try to derive 2 times for A, the compiler will not know what function A to use, the base A or the derived version of B.
al
you should read more about base and derived classes.
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.
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.