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.
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?
class A {
public:
virtual int test()=0;
};
class B : public A {
public:
int test(){return 10;}
};
B *b = new B();
b->test(); // would return 10;
whereas:
class A {
public:
int test(){return 0;}
};
class B : public A {
public:
int test(){return 10;}
};
B *b = new B();
b->test(); // **would return 0**;
Why does it return "0" here? This makes zero sense to me, because I assume that the (kind of overloaded) members of the derived class (B) come first!
What is happening here?
Apart from the invalid syntax (B->test(); where it should be b->test();), the second one will also return 10.
If instead you would have written:
A* a = new B();
a->test();
It would have returned 0 or 10 depending on whether A::test is virtual.
Why does the follwing code produce this error even though c is a struct and has a public inheritance by default??
struct c
{
protected:
int i;
public:
c(int ii=0):i(ii){}
virtual c *fun();
};
c* c::fun(){
cout<<"in c";
return &c();
}
class d : c
{
public:
d(){}
d* fun()
{
i = 9;
cout<<"in d"<<'\t'<<i;
return &d();
}
};
int main()
{
c *cc;
d dd;
cc = ⅆ
cc->fun();
}
You need:
class d : public c
class inheritance is private by default.
When you privately inherit from a class or a struct, you explicitly say, among other things, that direct conversion from a derived type to a base type isn't possible.
In the following lines class A is the base class, inherited by classes B and C.
Class D inherits from both B and C. Furthermore, the constructor in D calls constructors of B, C and A.
Because when B and C inherit A as virtual, they are not eligible to call constructor of A directly (as the call to same must be made through 3rd generation).
My question is, if I want to make an object of class B, then as A is inherited virtually, is there anyway to call constructor of A (to pass v1 and v2, the variables to be used for initialization)?
class A {
int a1,a2;
A() {
}
A(int v1,v2) {
a1 = v1;
a2 = v2;
}
};
class B:virtual public A {
int b1,b2;
B() {
}
B(int v1,v2) {
b1 = v1;
b2 = v2;
}
};
class C:virtual public A {
int c1,c2;
C() {
}
C(int v1,v2) {
c1 = v1;
c2 = v2;
}
};
class D:public B,public C {
int d1,d2;
D() {
}
D(int v1,v2):B(v1,v2),C(v1,v2),A(v1,v2)
{
d1 = v1;
d2 = v2;
}
};
It's perfectly fine to also give B an initializer for A. All that virtual inheritance means is that if you have an even-more-derived object, then the virtual base is constructed by the most-derived object. But if you're only constructing an instance of B, then that instance is the most derived object. So just write it like this:
class B : public virtual A
{
public:
B() : A(1, 2) { }
// ...
};
It's only when you derive from B that the base initializer is ignored.
What you can do is to make classes B and C inherit normally (without keyword 'virtual') from A, but make class D to inhert virtually from B and C. That will allow you to create object of class B (or C) by passing values for class A constructor>
If I have this class structure:
class A
{
public:
int a;
void funcA(){a = 0;}
};
class B
{
public:
int b;
void funcB(){b = 0;}
};
class C: public A, public B
{
public:
int c;
void funcC(){c = 0;}
};
Why can I perform this cast?
A* pA = new A;
C* pC = static_cast<C*> (pA);
B* pB = static_cast<B*> (pC);
pB->funcB();
A and B are unrelated, are they not?
They may be unrelated, but the compiler doesn't do inter-cast diagnosis here.
It just says "Oh, C is a derived class of A, that's legal as far as I'm concerned".
In the next line it says "Oh, B is a base class of C, that's legal as far as I'm concerned".
And that's about it. In your case, C links A and B between casts.