How instances of virtual base class are available to derived class? - c++

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
{
} ;

Related

Complex multiple inheritance situation

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.

Inheritance without duplicating code

I have 4 classes, lets say: class A, class B, class C and class D.
Class B inherits from class A.
Class C and class D inherit from class B.
Classes A and B are abstract classes.
I would like to declare a field in class A, lets say int posision and define this field in constructors of class C and class D by assigning value of the parameter (int parameterValue) to this field.
Is there any solution to do this without duplicating line position = parameterValue in all constructors of descendant classes?
You might use inherited constructor:
struct A
{
A(int position) : position(position) {}
virtual ~A() = default;
int position;
};
struct B : public A
{
using A::A;
};
struct C : public B
{
using B::B;
};
struct D : public B
{
using B::B;
};
Demo
Put it in class B and call the super constructor at the begining of the descendent classes. Like that:
class A {
protected:
int position;
};
class B: public A {
public:
B(int parameterValue) : A() {
position = parameterValue;
}
};
class C: public B {
public:
C(int parameterValue) : B(parameterValue) {
}
};

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

Diamond inheritance with mixed inheritance modifers (protected / private / public)

let's say we have class A,B,C,D where A is base, B,C are between and D is derived in diamond model.
NOTE:
class B inherits virtualy class A in private mode,
class C inherita virtualy class A in protected mode.
class A
{
public:
int member; // note this member
};
class B :
virtual private A // note private
{
};
class C :
virtual protected A // note protected
{
};
class D :
public B, // doesn't metter public or whatever here
public C
{
};
int main()
{
D test;
test.member = 0; // WHAT IS member? protected or private member?
cin.ignore();
return 0;
}
now when we make an instance of class D what will member be then? private or protected lol?
Figure No2:
what if we make it so:
class B :
virtual public A // note public this time!
{
};
class C :
virtual protected A // same as before
{
};
I suppose member will be public in this second example isn it?
§11.6 Multiple access [class.paths]
If a name can be reached by several paths through a multiple inheritance graph, the access is that of the path that gives most access. [ Example:
class W { public: void f(); };
class A : private virtual W { };
class B : public virtual W { };
class C : public A, public B {
void f() { W::f(); } // OK
};
Since W::f() is available to C::f() along the public path through B, access is allowed. —end example ]
I think I don't need to add anything else, but see also this defect report (which was closed as "not a defect").

when does ambiguity arise in multiple inheritance?

when does ambiguity arise in multiple inheritance?
When you have replicated base class in several paths of inheritance and you are trying to cast to it or call its member-function.
struct A { };
struct B : A { };
struct C : A { };
struct D : B, C { }; // has replicated A as the base class
D d;
A* a = static_cast<A*>(&d); // oops
The problem has several remedies which depend on the context heavily (using virtual base classes, just refine the aforementioned cast, etc.)
More info here, especially here.
One famous example of ambiguity in multiple inheritance is the so-called Diamond Problem.
Summary:
"In object-oriented programming languages with multiple inheritance and knowledge organization, the diamond problem is an ambiguity that arises when two classes B and C inherit from A, and class D inherits from both B and C. If a method in D calls a method defined in A (and does not override the method), and B and C have overridden that method differently, then from which class does it inherit: B, or C?"
You can find details here: Wikipedia: Diamond Problem
struct Base{
void foo(){
}
};
struct Derived1 : public Base{
};
struct Derived2 : public Base{
};
struct Final : public Derived1, public Derived2{
};
int main(){
Final f;
f.foo();
}
See on Ideone. To fix, simply use virtual inheritance:
struct Derived1 : virtual public Base{
};
struct Derived2 : virtual public Base{
};
Another possibility for ambigouty is the following:
struct Base1{
void foo(){
}
};
struct Base2{
void foo(){
}
};
struct Final : public Base1, public Base2{
};
int main(){
Final f;
f.foo();
}
Again, on Ideone. To fix, simple make do the following in Final:
struct Final : public Base1, public Base2{
using Base1::foo;
// or
// using Base2::foo;
};
When it makes names used unclear
class baseX
{
private:
void* callA();//will never be ambiguous.
protected:
void* callB();
public:
void* callC();
}
class baseY
{
private:
void* callA();//will never be ambiguous.
protected:
void* callB();
public:
void* callC();
}
class derived: public baseX, public baseY
{
void someMethod()
{
void* x = baseX::callB();//not ambiguous
void* y = baseY::callB();//not ambiguous
void* z = callB();//ambiguose
}
}
void someFunction(derived& d)
{
void* x = d.CallC();//ambiguous
}
Ambiguity can also happen when the same class is the base through more than one route:
class Base
{
public void call();
}
class DerivedX : public Base
{
}
class DerivedY : public Base
{
}
class GrandChild : public DerivedX, public DerivedY //What does call() do?
{
}
This can be solved with virtual bases:
class Base
{
public void call();
}
class DerivedX : public virtual Base
{
}
class DerivedY : public virtual Base
{
}
class GrandChild : public DerivedX, public DerivedY //only one "Base" class in inheritance, shared between DerivedX and DerivedY
{
}