C++: multiple inheritance using virtual - c++

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"

Related

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.

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

"a struct has public inheritance by default"

"a struct has public inheritance by default" what does this statement really mean? And why is the following code in error just because I have omitted the keyword 'public' while deriving the class d from c??
struct c
{
protected:
int i;
public:
c(int ii=0):i(ii){}
virtual c *fun();
};
c* c::fun(){
cout<<"in c";
return &c();
}
class d : c
{
public:
d(){}
d* fun()
{
i = 9;
cout<<"in d"<<'\t'<<i;
return &d();
}
};
int main()
{
c *cc;
d dd;
cc = &dd;
cc->fun();
}
It means that
struct c;
struct d : c
is equivalent to
struct d : public c
Your code is a class extending a struct:
struct c;
class d : c;
is equivalent to
class d : private c;
because class has private inheritance by default.
And it means that all inherited and not overriden/overloaded/hidden methods from c are private in d.
"a struct has public inheritance by default" means that this
struct Derived : Base {};
is equivalent to
struct Derived : public Base {};
Classes have private inheritance by default, so when you remove the public from a class inheritance you have the equivalent of
class Derived : private Base {};
In this private inheritance scenario, Derived does not have an is-a relationship with Base, it essentially has-a Base. So the conversion you are trying to attempt here:
cc = &dd;
is not allowed.
When you write a struct and inherit from something without specifying an access specifier, that inheritance is treated as public. When you write a class and inherit from something without specifying an access specifier (even if that something is a struct), that inheritance is treated as private. In your code, you're doing the latter, so the inheritance is private, hence the observed error.
Put another way, to say that struct inheritance is public by default really means that inheritance done when writing a struct is public by default, not that inheriting from a struct is public by default.

C++ Multiple Inheritance - why you no work?

I am trying to figure out an interesting multiple inheritance issue.
The grandparent is an interface class with multiple methods:
class A
{
public:
virtual int foo() = 0;
virtual int bar() = 0;
};
Then there are abstract classes that are partially completing this interface.
class B : public A
{
public:
int foo() { return 0;}
};
class C : public A
{
public:
int bar() { return 1;}
};
The class I want to use inherits from both of the parents and specifies what method should come from where via using directives:
class D : public B, public C
{
public:
using B::foo;
using C::bar;
};
When I try to instantiate a D I get errors for trying to instantiate an abstract class.
int main()
{
D d; //<-- Error cannot instantiate abstract class.
int test = d.foo();
int test2 = d.bar();
return 0;
}
Can someone help me understand the problem and how to best make use of partial implementations?
You don't have diamond inheritance. The B and C base classes of D each have their own A base class subobject because they do not inherit virtually from A.
So, in D, there are really four pure virtual member functions that need to be implemented: the A::foo and A::bar from B and the A::foo and A::bar from C.
You probably want to use virtual inheritance. The class declarations and base class lists would look like so:
class A
class B : public virtual A
class C : public virtual A
class D : public B, public C
If you don't want to use virtual inheritance then you need to override the other two pure virtual functions in D:
class D : public B, public C
{
public:
using B::foo;
using C::bar;
int B::bar() { return 0; }
int C::foo() { return 0; }
};
You need to make your base classes virtual in order for them to inherit properly. The general rule is that all non-private member functions and base classes should be virtual UNLESS you know what you're doing and want to disable normal inheritance for that member/base.

Interface-like inheritance in C++

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