Diamond inheritance in Multiple Inheritance using the Virtual keyword [duplicate] - c++

This question already has answers here:
Order of constructor call in virtual inheritance
(3 answers)
Closed 7 years ago.
I've heard that using the virtual keyword solves the diamond problem.
However, when I did this:
#include <iostream>
using namespace std;
class A {
public:
A(int x = 100) {
num = x;
}
protected:
int num;
};
class B1 : virtual public A{
public:
B1(int x = 50) : A(2*x) {
}
};
class B2 : virtual public A{
public:
B2(int x = 50) : A(2*x) {
}
};
class C : public B1, public B2 {
public:
C(int x = 75) : B1(2*x), B2(2*x) {};
int getData(){ return num; }
};
int main() {
C c(10);
cout << c.getData();
cin.get();
return 0;
}
It displays the output as 100 instead of what I expected, i.e. 40. Why?

When you use virtual inheritance, you are guaranteed to have one single instance of the common base class (cite); therefore, B1 and B2 cannot have their own instance of A, but they will share a single instance with C. For instance, if you define C's constructor as follows:
C(int x = 75) : B1(2*x), B2(2*x), A(x) {};
you'll see your code outputs 10. The key is in what #dyp has commented:
the common base class is initialized in the most derived class
(Of course in the example above it doesn't make any sense to have all B1, B2 and A in the initializer list, as having Awill suffice).

Related

How to initialize an `const int` member in a base class when constructing child? [duplicate]

This question already has answers here:
How can I initialize base class member variables in derived class constructor?
(7 answers)
Closed 24 days ago.
#include <iostream>
class A {
public:
const int HP = 200;
A(){
std::cout << this->HP << std::endl;
}
};
class B : public A {
public:
B();
};
Constructing a B object will construct the A potion first.
I expect to reinitialize HP so that B() can print new HP.
Is this feasible for a base class const member ?
I need a member shared between base and child but to be constant in one instance of class, any suggestions?
You can add a constructor to A (and if needed also to B) that accepts the value for the const int member.
Then when you invoke A constructor from B constructor via the initializer list, you can pass this const value to the base.
Code example:
#include <iostream>
class A {
public:
const int HP = 200;
A() {
std::cout << this->HP << std::endl;
}
//----vvvvvv----vvvvvv--
A(int hp) : HP(hp) {
std::cout << this->HP << std::endl;
}
};
class B : public A {
public:
B() {};
//----vvvvvv----vvvvv--
B(int hp) : A(hp) {}
};
int main()
{
B b1;
B b2{ 99 };
}
Output:
200
99
Note: B can also be left as is (without an additional constructor), and pass the required const value to the base.

c++ how do i get a specific value from a specific inherited class

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?

C++ how to access value of inherited and overridden attribute of base class?

I try to do something like this:
class A{
public:
A(){number = 1;}
int number;
};
class B : public A{
public:
B(){number = 2;}
};
class Base {
public:
Base() {myAttribute = new A();}
int returnAttrNumber(){return myAttribute->number;}
A *myAttribute;
};
class Inherited : public Base{
public:
Inherited(){myAttribute = new B();}
B *myAttribute;
};
int main()
{
Inherited *i = new Inherited();
std::cout << i->returnAttrNumber(); // outputs 1, because it gets the A not the B. I want it to output 2, to get the B object in returnAttrNumber()
}
So, class Base holds an object A. Inherited holds an A-derived object B. And I try to call a method on the base class, but I want it to cast down in the hirarchy of the corresponding Object as far as possible (without static_cast or dynamic_cast) and then take the B object, not A and do stuff (returning it's number in in this case)
Is there a way to do that downcasting from a base class in C++ without big difficulties?
Thanks for answers!
This is very bad design. The quick answer is you can access variable from the base class via the fully qualified identifier. Take the following example:
#include <iostream>
class A
{
public:
A()
: var(1) {}
protected:
int var;
};
class B : public A
{
public:
B()
: var(2) {}
int getBVar() const
{
return var;
}
int getAVar() const
{
return A::var;
}
private:
int var;
};
int main()
{
B b;
std::cout << "A: " << b.getAVar() << std::endl;
std::cout << "B: " << b.getBVar() << std::endl;
}
Which outputs the following:
A: 1
B: 2
About the down casting bit... Base and Inherited have different variables. You can not safely case one to the other.
Well as rioki said,
Base and Inherited have different variables
This is because I redeclared MyAttribute as a B in Inherited. This was the mistake. I thought, when I declare it with the same name, it will be the same variable, that's wrong.
So the whole solution for this is to uncomment this one line in Inherited. Working code:
class A{
public:
A(){number = 1;}
int number;
};
class B : public A{
public:
B(){number = 2;}
};
class Base {
public:
Base() {myAttribute = new A();}
int returnAttrNumber(){return myAttribute->number;}
A *myAttribute;
};
class Inherited : public Base{
public:
Inherited(){myAttribute = new B();}
//B *myAttribute;
};
int main()
{
Base *i = new Inherited(); // this works, what is necessary in my case
std::cout << i->returnAttrNumber(); // outputs 2 now
}

c++ virtual public inheritance init strange result? [duplicate]

This question already has answers here:
c++ virtual inheritance
(3 answers)
Closed 10 years ago.
The output of the program below is:
5
5
#include <iostream>
using namespace std;
struct A
{
public:
int myInt;
A(int n): myInt(n){}
A(): myInt(5) {}
};
class B : virtual public A
{
public:
B(int n):A(10) {}
B():A(10) {}
};
class C : virtual public A
{
public:
C(int n):A(3*n) {}
};
class D : public B, public C
{
public:
D(int n=90) : C(2*n), B(n) {}
};
class E : public D
{
public:
E(int n=20):D(n-1) {}
};
int main()
{
D d(100);
cout << d.myInt << endl;
E e;
cout << e.myInt << endl;
return 0;
}
Consider the object d. From what I understand the inheritance is constructed based on the order of the inheritance list (rather than the initialization list) so B class is constructed first with the param 100 which goes to class A with the parameter 10. So now A sets myInt to the value 10. The same goes for Class c and because myInt is virtual then it is set to the number 600. I never expected 5. why is this happening?
See article in parashift:
Because a virtual base class subobject occurs only once in an
instance, there are special rules to make sure the virtual base
class's constructor and destructor get called exactly once per
instance. The C++ rules say that virtual base classes are constructed
before all non-virtual base classes. The thing you as a programmer
need to know is this: constructors for virtual base classes anywhere
in your class's inheritance hierarchy are called by the "most derived"
class's constructor.

Struct inheritance in C++

Can a struct be inherited in C++?
Yes, struct is exactly like class except the default accessibility is public for struct (while it's private for class).
Yes. The inheritance is public by default.
Syntax (example):
struct A { };
struct B : A { };
struct C : B { };
Other than what Alex and Evan have already stated, I would like to add that a C++ struct is not like a C struct.
In C++, a struct can have methods, inheritance, etc. just like a C++ class.
In C++, a structure's inheritance is the same as a class except the following differences:
When deriving a struct from a class/struct, the default access-specifier for a base class/struct is public. And when deriving a class, the default access specifier is private.
For example, program 1 fails with a compilation error and program 2 works fine.
// Program 1
#include <stdio.h>
class Base {
public:
int x;
};
class Derived : Base { }; // Is equivalent to class Derived : private Base {}
int main()
{
Derived d;
d.x = 20; // Compiler error because inheritance is private
getchar();
return 0;
}
// Program 2
#include <stdio.h>
struct Base {
public:
int x;
};
struct Derived : Base { }; // Is equivalent to struct Derived : public Base {}
int main()
{
Derived d;
d.x = 20; // Works fine because inheritance is public
getchar();
return 0;
}
Of course. In C++, structs and classes are nearly identical (things like defaulting to public instead of private are among the small differences).
Yes, c++ struct is very similar to c++ class, except the fact that everything is publicly inherited, ( single / multilevel / hierarchical inheritance, but not hybrid and multiple inheritance )
here is a code for demonstration
#include<bits/stdc++.h>
using namespace std;
struct parent
{
int data;
parent() : data(3){}; // default constructor
parent(int x) : data(x){}; // parameterized constructor
};
struct child : parent
{
int a , b;
child(): a(1) , b(2){}; // default constructor
child(int x, int y) : a(x) , b(y){};// parameterized constructor
child(int x, int y,int z) // parameterized constructor
{
a = x;
b = y;
data = z;
}
child(const child &C) // copy constructor
{
a = C.a;
b = C.b;
data = C.data;
}
};
int main()
{
child c1 ,
c2(10 , 20),
c3(10 , 20, 30),
c4(c3);
auto print = [](const child &c) { cout<<c.a<<"\t"<<c.b<<"\t"<<c.data<<endl; };
print(c1);
print(c2);
print(c3);
print(c4);
}
OUTPUT
1 2 3
10 20 3
10 20 30
10 20 30