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
Related
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.
Still learning basics of C++
I have a very simple query regarding the virtual keyword in multiple inheritance.
I have the following code:
class A {};
class B : public A {};
//1. class C : public A, public B {};
//2. class C : virtual public A, public B {};
//3. class C : public A, virtual public B {};
//4. class C : virtual public A, virtual public B {};
int main() {
C f;
return 0;
}
Now I know (by actually trying this code out), that 1 and 3, both cases where we do not use virtual keyword while inheriting class A work.
I understand it is the Diamond Problem of multiple inheritance, and the compiler error goes away when I inherit class A as virtual in class B:
class B: virtual public A
But I wanted to experiment with the code and removed it.
My question is, Why does creation of an object of class C fail when we inherit class A using virtual?
Note: I could not find a good article to explain in depth what this virtual keyword means and how the compiler reads it and what does the compiler do after reading the Virtual Keyword.
EDIT:
This is an experiment that I am doing, so no practical use (to me personally).
When do this:
class A {};
class B : public A {};
class C : virtual public A, virtual public B {};
int main() {
C f;
return 0;
}
Compiler throws error: error C2584: 'C': direct base 'A' is inaccessible; already a base of 'B'
even when I don't use virtual, compiler still gives the error msg as a "Warning"
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.
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
{
} ;
I have the following situation, pictured is the theoretical inheritance graph of my classes:
The idea is basically to
1) have two abstract base classes that can be implemented on different platforms (in my case two different operating systems)
2) allow BBase to be up-castable to ABase to be able to handle both equally at times (e.g. to hold instances of both types in one list).
3) implement certain common functionality in ABase and BBase.
Now, what would be the best way to represent this in C++? Even though it does support multiple inheritance, multi-level inheritence like this is not possible to my knowledge. The problem is that B inherits from A and BBase, which both in turn inherit from ABase. Simply translating this 1:1 (following code) in C++, a C++ compiler (GNU) will complain that ABase::foo() is not implemented in B.
class ABase
{
public:
virtual void foo() = 0;
void someImplementedMethod() {}
};
class BBase : public ABase
{
public:
virtual void bar() = 0;
void someOtherImplementedMethod() {}
};
class A : public ABase
{
public:
A() {}
void foo() {}
};
class B : public A, public BBase
{
public:
B() : A() {}
void bar() {}
};
int main()
{
B b;
return 0;
}
How would you change this inheritance model to make it compatible to C++?
EDIT: Inverted arrows in diagram and corrected "down-castable" to "up-castable".
You can directly use that type of hierarchy in C++ by using virtual inheritance:
class ABase{...};
class BBase : public virtual ABase {...};
class A : public virtual ABase {...};
class B : public A, public BBase {...};
Of course if you plan on having more levels, it might be a good idea to use virtual inheritance for B too, so you would get
class B : public virtual A, public virtual BBase {...};