I've been asked to make a program which has a base class, two derived children classes from it, and then another one which is derived from both children. The assignment asks me to inherit half the attributes from one child and the rest from the other one. (Hope this makes sense to you). These attributes are not specific of the children, but of the base class. This is my code:
# include <iostream>
class Base {
protected:
int _var1;
int _var2;
int _var3;
int _var4;
public:
Base() : _var1(10), _var2(20), _var3(30), _var4(40) {}
virtual ~Base() {};
int getVar1() const { return this->_var1; }
int getVar2() const { return this->_var2; }
int getVar3() const { return this->_var3; }
int getVar4() const { return this->_var4; }
};
class Child1 : public virtual Base {
public:
Child1() { _var1 = 100; _var2 = 200; _var3 = 300; _var4 = 400;}
virtual ~Child1() {}
};
class Child2 : public virtual Base {
public:
Child2() { _var1 = 500; _var2 = 600; _var3 = 700; _var4 = 800;}
virtual ~Child2() {}
};
class GrandChild : public Child1, public Child2 {
public:
GrandChild() {}
virtual ~GrandChild() {}
};
int main() {
Child1 c;
Child2 d;
GrandChild g;
std::cout << c.getVar1() << std::endl;
std::cout << d.getVar1() << std::endl;
std::cout << g.getVar1() << std::endl;
}
With this code, g instance automatically inherits the attributes from Child2, but I want to pick which attributes it inherits from which class, e.g. _var1 from Child1 and _var3 from Child2. Is that even possible? Thank you so much in advance :)
I stripped the unrelated parts off your code (every thing public, and no need to declare the virtual destructor again):
#include <iostream>
struct Base {
int var1;
int var2;
Base() : var1(10),var2(20) {}
virtual ~Base() {};
};
struct Child1 : virtual Base {
Child1() { var1 = 100; var2 = 200; }
};
struct Child2 : virtual Base {
Child2() { var1 = 500; var2 = 600;}
};
struct GrandChild : Child1, Child2 {
GrandChild() {}
};
int main() {
Child1 c;
Child2 d;
GrandChild g;
std::cout << c.var1 << std::endl;
std::cout << d.var1 << std::endl;
std::cout << g.var1 << std::endl;
}
It produces the same output:
100
500
500
This is because, the Grandchild
constructor is equivalent to:
GrandChild() : Base(),Child1(),Child2() {}
A virtual base is always initialized by the most derived class. Then the Child1
and Child2
subobjects are initialized by calling their constructor. They are called in this order, because thats the order here struct GrandChild : Child1, Child2
.
Thats why you see 500
on the last line of output. First, the Base
constructor initializes var1
to 10
. Next the Child1
constructor assigns 100
. And eventually the Child2
constructor assigns 500
.
You cannot selectively inherit only some members. I suppose what you want is to let Child1
assign 100
to var1
and Child2
assign 600
to var2
. Note that initialization of this members already happened when GrandChild
called the constructor of Base
. Because Base
is a virtual base class and GrandChild
is the most derived class, neither Child1
nor Child2
have any buisness in initializing the members var1
and var2
of GrandChild
.
You can however, write constructors that assign only some of the inherited members:
#include <iostream>
struct Base {
int var1;
int var2;
Base() : var1(10),var2(20) {}
virtual ~Base() {};
};
struct Child1 : virtual Base {
Child1() { var1 = 100; }
};
struct Child2 : virtual Base {
Child2() { var2 = 600;}
};
struct GrandChild : Child1, Child2 {
GrandChild() : Base(),Child1(),Child2() {}
};
int main() {
GrandChild g;
std::cout << g.var1 << std::endl;
std::cout << g.var2 << std::endl;
}
100
600