Complex multiple inheritance situation - c++

class diagram
class A {public: virtual int func();};
class B: virtual public A {};
class C: virtual public A {};
class D: virtual public C {public: virtual int func();};
class E: public B, public D {};
// e is an object of E
e->func(); // this will run func defined in A, not in D
I have a multiple inheritance situation as in the above example. How can I implement this to call the most derived method? (To call func() implemented in D, not in A, when I write e->func())

If you have implemented func in D, that will be called. You can see the running example here
https://ideone.com/kwJubg
class A {public: virtual int func(){cout<<"In A";};};
class B: virtual public A {};
class C: virtual public A {};
class D: virtual public C {public: virtual int func(){cout<<"In D";};};
class E: public B, public D {};
int main()
{
E *e = new E();
e->func();
return 0;
}

When I test your example I get "D" not "A" as you mentioned.
class A {public: virtual void func() {std::cout << "A" << std::endl;} };
class B: virtual public A {};
class C: virtual public A {};
class D: virtual public C {public: virtual void func() {std::cout << "D" << std::endl;} };
class E: public B, public D {};
int main()
{
E e {};
e.func();
}
You have the "Diamond" problem.
A
B D // only B or D can override A::func()
E // can override A::func()
The tip of the Diamond is class A, and it has two classes that derive from it, "B" and "D", on each side of the diamond. Only one of the derived classes that are part of the sides of the diamond can override a virtual function from the tip of the diamond, not both of them (Note that the bottom of the diamond can override, in this case E). In this case is class D which overrides func. If class B would override func it wouldn't compile. Also if class "B" and "D" don't override anything, in your example, A::func() would be called.

Related

"If the deriving class does not inherit the base class virtually, then all virtual methods must be defined".How to understand that in the right way?

As per the wiki, which says that[emphasise mine]:
Note the code snippet in the quotaion is seen here.
Suppose a pure virtual method is defined in the base class. If a
deriving class inherits the base class virtually, then the pure
virtual method does not need to be defined in that deriving class.
However, if the deriving class does not inherit the base class
virtually, then all virtual methods must be defined. The code below
may be explored interactively here.
#include <string>
#include <iostream>
class A {
protected:
std::string _msg;
public:
A(std::string x): _msg(x) {}
void test(){ std::cout<<"hello from A: "<<_msg <<"\n"; }
virtual void pure_virtual_test() = 0; };
// since B,C inherit A virtually, the pure virtual method >pure_virtual_test doesn't need to be defined
class B: virtual public A
{ public: B(std::string x):A("b"){} };
class C: virtual public A {
public: C(std::string x):A("c"){} };
// since B,C inherit A virtually, A must be constructed in each child
// however, since D does not inherit B,C virtually, the pure virtual method in A *must be defined*
class D: public B,C {
public:
D(std::string x):A("d_a"),B("d_b"),C("d_c"){}
void pure_virtual_test() override { std::cout<<"pure virtual hello from: "<<_msg <<"\n"; } };
// it is not necessary to redefine the pure virtual method after the
parent defines it class E: public D {
public:
E(std::string x):A("e_a"),D("e_d"){} };
int main(int argc, char ** argv){
D d("d");
d.test(); // hello from A: d_a
d.pure_virtual_test(); // pure virtual hello from: d_a
E e("e");
e.test(); // hello from A: e_a
e.pure_virtual_test(); // pure virtual hello from: e_a
}
How to understand the statement in bold in the right way?
It seems that if the deriving class(i.e. class B) does not inherit the base class virtually, then virtual methods can be left undefined.Here is my demo code snippet to support what I say:
#include <string>
#include <iostream>
class A {
protected:
std::string _msg;
public:
A(std::string x): _msg(x) {}
void test(){ std::cout<<"hello from A: "<<_msg <<"\n"; }
virtual void pure_virtual_test() = 0;
};
// Attention: B does not inherit A ***virtually***, the pure virtual method pure_virtual_test doesn't need to be defined, either.
class B: public A { public: B(std::string x):A("b"){} };
class D: public B {
public:
D(std::string x):B("d_b"){}
void pure_virtual_test() override { std::cout<<"pure virtual hello from: "<<_msg <<"\n"; }
};
// it is not necessary to redefine the pure virtual method after the parent defines it
class E: public D {
public:
E(std::string x):D("e_d"){}
};
int main(int argc, char ** argv){
D d("d");
d.test();
d.pure_virtual_test();
E e("e");
e.test();
e.pure_virtual_test();
}
The description in the wikipedia article is wrong/misleading.
"If the deriving class does not inherit the base class virtually, then all virtual methods must be defined" is only true if the deriving class gets instantiated. A mere declaration, without instantiation, does not require definition of pure virtual methods.
The wikipedia article's claim that "since D does not inherit B,C virtually, the pure virtual method in A must be defined" is simply not true, and the following compiles without any issues, without either D or E instantiating the pure virtual method:
#include <string>
#include <iostream>
class A {
protected:
std::string _msg;
public:
A(std::string x): _msg(x) {}
void test(){ std::cout<<"hello from A: "<<_msg <<"\n"; }
virtual void pure_virtual_test() = 0;
};
// since B,C inherit A virtually, the pure virtual method pure_virtual_test doesn't need to be defined
class B: virtual public A { public: B(std::string x):A("b"){} };
class C: virtual public A { public: C(std::string x):A("c"){} };
class D: public B,C {
public:
D(std::string x):A("d_a"),B("d_b"),C("d_c"){}
};
class E: public D {
public:
E(std::string x):A("e_a"),D("e_d"){}
};
int main()
{
return 0;
}
main is left empty, and D and E are declared without issues. Now, if you try to instantiate one or the other, then you're going to have problems.
The quoted text seems to be referring to a rule called dominance, which leads to a situation where it sort of looks like a virtual function isn't being overridden, even though it is. Here's an example:
struct base {
virtual void f();
};
struct i1 : base {
// doesn't override base::f
};
struct i2 : base {
void f() {} // overrides base::f
struct derived : i1, i2 {
};
With this hierarchy, you can write
derived d;
d.f(); // illegal, because ambiguous:
// i1::f, inherited from base, or i2::f
i1* p = &d;
p->f(); // calls base::f
Easy enough, right? Now let's make the inheritance from base virtual. Here's where dominance kicks in:
struct base {
virtual void f();
};
struct i1 : virtual base {
// doesn't override base::f
};
struct i2 : virtual base {
void f() {} // overrides base::f
struct derived : i1, i2 {
};
Now there's only one base sub-object, and i2::f overrides base::f, even in i1:
derived d;
d.f(); // calls i2::f
i1* i1p = &d;
i1p->f(); // calls i2::f
Yes, the call i1p->f() calls i2's version of f, even though i1 doesn't know anything about i2. It's only because i1 and i2 are both base classes of derived and both have base as a virtual base that this works. The compiler has to get the code right for this cross-hierarchy call.
Making base::f pure virtual doesn't change the rules about finding its overriders. So with non-virtual inheritance, i1 doesn't override base::f, and derived is an abstract class. But with virtual inheritance, i2::f overrides base::f, and the class derived is not abstract.

Is declaring a class in C++ as "final : public virtual" EVER useful?

When declaring a c++ class as final, is it ever needed to inherit base classes using virtual inheritance? I know what virtual inheritance is for and use it to avoid member duplication.
As an example, if I have these class definitions (imagine all of them having some members and virtual deconstructors)
class B : public virtual A {};
class C : public virtual A {};
class D : public virtual C {};
Does it make sense to define a next class as
class E final : public virtual D {}
or
class F final : public virtual B, public virtual C {};
or is the default inheritance, i.e.
class E final : public D {}
class F final : public B, public C {};
always enough?
This has bothered me for a long time now, as I see from time to time code, that includes
"final : public virtual"
Could the virtual be safely omitted here in any case?
Any hints/explanations are greatly appreciated
struct A { void foo() { cout << "foo" << endl; } };
struct B : virtual A {};
struct D final : virtual A, B {};
D d;
d.foo();
Without virtual before A call to foo would be ambiguous.

Deviation with virtual keyword

I have below structure defied as
struct A{
string s;
A() {
cout<<"in a default\n";
}
A(string t): s(t) {
cout<<"in a param \n";
}
};
struct B: virtual public A{
B(): A("B"){
cout<<"in b\n";
}
};
struct C: virtual public A {};
struct D: public B, public C {};
int main()
{
D d;
}
with A as virtual base class in both C and B,output is as follows
in a default
in b
With A as virtual base class for only B ,output is as follows
in a default
in b
in a default
with A as virtual base class for only C ,output is as follows
in a default
in a param
in b
and with no virtual base class ,output is as follows
in a param
in b
in a default
can any one explain me the deviation?
Virtual inheritance is there to resolve what's known as the "Diamond of death"
In summary, the issue is that if you called D::[some function in A], which A would it pick - the one from B, or the one from C, or that makes no sense that the separation exists?
You can read more about the issue here.
https://en.wikipedia.org/wiki/Multiple_inheritance#The_diamond_problem

How instances of virtual base class are available to derived class?

How instances of virtual base class are available to derived class,How it can be implemented in following code ?
class A
{
public:
void test();
};
class B : virtual public A
{
};
class c : public A
{
} ;
class D : public B, public C
{
};
See inscribed comments with corrected version:
class A
{
public:
void test();
};
class B: virtual public A // A is a virtual base class
{
};
class C : public A // C is a base class of A
{
} ;
class D: public B, public C // D has two base classes B and C
{
};
By virtue of inheritance, D gets two copies of A, one via B, another via C
You could have only one shared copy of A in D, if you would have declared:
class C : virtual public A // C is a virtual base class of A
{
} ;

Virtual Base Class in C++

I have a query regarding the virtual base class. In order to resolve the "dreaded diamond of death" /ambiguity problem in multiple inheritance, virtual base class is introduced.
class A { public: void Foo() {} };
class B : public virtual A {};
class C : public virtual A {};
class D : public B, public C {};
What will happen when a keyword virtual is not used in class C declaration. Could you please explain me in detail?
class A { public: void Foo() {} };
class B : public virtual A {};
class C : public A {};
class D : public B, public C {};
If your inheritance is not virtual then A members will be present twice in D class.
If A had a field named _a, then, in D, writing B::_a or C::_a would refer to two different memory zones. If your inheritance is virtual then you have only one memory zone.
If you are using virtual than there will be no ambiguity when you call foo() using the instance of Class D. and if you are not using virtual than it will be ambiguity..
But be careful that virtual inheritance cost more so use it carefully..
class A { public: void Foo() {} };
class B : public virtual A {};
class C : public A {};
class D : public B, public C {};
If the inheritance from the A class to B marked virtual but not A class to C, then C++ will create a single virtual A (D inherits B, B inherits A) and a nonvirtual A (D inherits C, C inherits A). Therefore, your code will not solve the diamond problem:
D d_object;
A &a_ref = d_object; // error raised -> B::A or C::A