C++ A multiple inheritance pproblem with pure virtual functions - c++

I have produced a minimal example to replicate the problem I am seeing with a more complex class hierarchy structure:
#include <string>
#include <iostream>
class A
{
protected:
virtual
~A() = 0;
};
inline
A::~A() {}
class B : public A
{
public:
virtual
~B()
{
}
std::string B_str;
};
class BB : public A
{
public:
virtual
~BB()
{
}
std::string BB_str;
};
class C : public A
{
protected:
virtual
~C()
{
}
virtual
void Print() const = 0;
};
class D : public B, public BB, public C
{
public:
virtual
~D()
{
}
};
class E : public C
{
public:
void Print() const
{
std::cout << "E" << std::endl;
}
};
class F : public E, public D
{
public:
void Print_Different() const
{
std::cout << "Different to E" << std::endl;
}
};
int main()
{
F f_inst;
return 0;
}
Compiling with g++ --std=c++11 main.cpp produces the error:
error: cannot declare variable ‘f_inst’ to be of abstract type ‘F’
F f_inst;
note: because the following virtual functions are pure within ‘F’:
class F : public E, public D
^
note: virtual void C::Print() const
void Print() const = 0;
^
So the compiler thinks that Print() is pure virtual.
But, I have specified what Print() should be in class E.
So, I've misunderstood some of the rules of inheritance.
What is my misunderstanding, and how can I correct this problem?
Note: It will compile if I remove the inheritance : public D from class F.

Currently your F is derived from C in two different ways. This means that an F object has two separate C bases, and so there are two instances of C::Print().
You only override the one coming via E currently.
To solve this you must take one of the following options:
Also override the one coming via D, either by implementing D::Print() or F::Print()
Make Print non-pure
Use virtual inheritance so that there is only a single C base.
For the latter option, the syntax adjustments would be:
class E : virtual public C
and
class D : public B, public BB, virtual public C
This means that D and E will both have the same C instance as their parent, and so the override E::Print() overrides the function for all classes 'downstream' of that C.
For more information , look up "diamond inheritance problem". See also Multiple inheritance FAQ

Related

C++ unable to find method definition from base class [duplicate]

I have produced a minimal example to replicate the problem I am seeing with a more complex class hierarchy structure:
#include <string>
#include <iostream>
class A
{
protected:
virtual
~A() = 0;
};
inline
A::~A() {}
class B : public A
{
public:
virtual
~B()
{
}
std::string B_str;
};
class BB : public A
{
public:
virtual
~BB()
{
}
std::string BB_str;
};
class C : public A
{
protected:
virtual
~C()
{
}
virtual
void Print() const = 0;
};
class D : public B, public BB, public C
{
public:
virtual
~D()
{
}
};
class E : public C
{
public:
void Print() const
{
std::cout << "E" << std::endl;
}
};
class F : public E, public D
{
public:
void Print_Different() const
{
std::cout << "Different to E" << std::endl;
}
};
int main()
{
F f_inst;
return 0;
}
Compiling with g++ --std=c++11 main.cpp produces the error:
error: cannot declare variable ‘f_inst’ to be of abstract type ‘F’
F f_inst;
note: because the following virtual functions are pure within ‘F’:
class F : public E, public D
^
note: virtual void C::Print() const
void Print() const = 0;
^
So the compiler thinks that Print() is pure virtual.
But, I have specified what Print() should be in class E.
So, I've misunderstood some of the rules of inheritance.
What is my misunderstanding, and how can I correct this problem?
Note: It will compile if I remove the inheritance : public D from class F.
Currently your F is derived from C in two different ways. This means that an F object has two separate C bases, and so there are two instances of C::Print().
You only override the one coming via E currently.
To solve this you must take one of the following options:
Also override the one coming via D, either by implementing D::Print() or F::Print()
Make Print non-pure
Use virtual inheritance so that there is only a single C base.
For the latter option, the syntax adjustments would be:
class E : virtual public C
and
class D : public B, public BB, virtual public C
This means that D and E will both have the same C instance as their parent, and so the override E::Print() overrides the function for all classes 'downstream' of that C.
For more information , look up "diamond inheritance problem". See also Multiple inheritance FAQ

Multiple virtual inheritance

I know there are many questions out there concerning MI, however, none seemed to answer my question. I have the following minimal example:
#include <iostream>
struct Base{
virtual void foo() = 0;
};
struct A : public virtual Base{
void foo(){
std::cout << "A::foo()" << std::endl;
}
void foo( int a){
std::cout << "A::foo(int a)" << std::endl;
}
};
struct B : public virtual Base{
virtual void foo( int a ) = 0;
};
struct C : public B,public A{
using A::foo;
};
int main( int argc, char* argv[]){
C c;
c.foo();
c.foo( 1 );
}
where Base, and B are entirely virtual classes and A provides all the implementation. However, the code does not compile but instead gives me the following error message
mh.cpp: In function ‘int main(int, char**)’:
mh.cpp:22:11: error: cannot declare variable ‘c’ to be of abstract type ‘C’
C c;
^
mh.cpp:17:12: note: because the following virtual functions are pure within ‘C’:
struct C : public B,public A{
^
mh.cpp:15:22: note: virtual void B::foo(int)
virtual void foo( int a ) = 0;
The behaviour I desire can be achieved by extending class C to
struct C : public B,public A{
using A::foo;
void foo( int a ){
A::foo( a );
}
};
However, I'd prefer not adding this redundant method. Is there some way I can achieve that result?
A::foo(int) can't override B::foo(int) unless A derives from B.
So, if you don't want to create the forwarding override in C, your alternatives are:
move the foo(int) pure virtual overload into Base
make A derive from B
restructure your interfaces so you don't need diamond-shaped virtual inheritance in the first place
No, if you inherit from a pure virtual class and you want to use this derived class (declare object of that type, not a pointer), you must implement all its pure virtual methods.
In the same manner you could ask the following:
class A
{
public:
virtual void foo()=0;
virtual void hello()=0;
}
class B: public A
{
public:
void myFoo();
void hello() { std::cout << "Hello!"; }
}
In class B, I don't want to use A::foo() but only B::myFoo() what should I do?
In such case you either need to provide some dummy implementation for the pure virtual function or review again your design... probably you should not inherit from A.
Similar thing is in your case. Probably your class C should not inherit from class B.
Just replace your single line as below.
Derived C only from A.
Your code
struct C : public B,public A{
using A::foo;
};
Replace above code with below code,
struct C : public A{
using A::foo;
};

C++ multiple inheritance with base classes deriving from the same class

I have stumbled on a problem while trying to re-use code from different classes. I post it here in hope that some of you might be able to help me.
I have a set of classes (B,C) deriving from the same class (A) which forces the implementation of some methods (foo, run). Class B implements these method, and both B and C provide other methods:
#include<iostream>
template<class I, class O>
class A {
public:
A() {}
virtual ~A() {}
virtual void foo() const = 0; // force implementation of this function
virtual void run() const = 0; // force implementation of this function
};
template<class I, class O>
class B : public A<I,O> {
public:
B() {}
virtual ~B() {}
virtual void foo() const { // implementation for the Base class
std::cout << "B's implementation of foo" << std::endl;
}
virtual void run() const { // implementation for the Base class
std::cout << "B's implementation of run" << std::endl;
}
virtual void foobar() const { // some other function provided by this class
std::cout << "B's implementation of foobar" << std::endl;
}
};
template<class I, class O, class M>
class C : public A<I,O> {
public:
C() {}
virtual ~C() {}
virtual void bar(M m) const { // some other function provided by this class
std::cout << "C's implementation of bar with: " << m << std::endl;
}
};
Now, what I am trying to do is inherit from both B and C so that I can have the extra methods (foobar, bar), but also not have to implement the method from class A (foo) because it is already defined in B:
template<class I, class O>
class D : public B<I,O>, public C<I,O,int> {
public:
D() {}
void run() const {
this->bar(123);
this->foo();
this->foobar();
}
};
But for some reason the compiler gives me this error:
test.cpp: In function ‘int main(int, char**)’:
test.cpp:68:35: error: cannot allocate an object of abstract type ‘D<float, double>’
A<float, double> *d = new D<float, double>(); // what I need to do
test.cpp:48:11: note: because the following virtual functions are pure within ‘D<float, double>’:
class D : public B<I,O>, public C<I,O,int> {
^
test.cpp:9:22: note: void A<I, O>::foo() const [with I = float; O = double]
virtual void foo() const = 0; // force implementation of this function
This is the code I use to run it:
int main(int argc, char **argv)
{
A<float, double> *b = new B<float, double>();
b->foo(); // prints "B's implementation of foo"
b->run(); // prints "B's implementation of run"
//A<float, double> *c = new C<float, double, int>(); // obviously fails because C does not implement any of A's functions
//A<float, double> *d = new D<float, double>; // line 68: what I need to do
//d->run(); // ***throws the abstract class error
return 0;
}
I want to use the 'run' function of an object of class D from a pointer to a A. As all the functions are virtual I expect to execute implementation of each function defined in the lowest inheritance point, meaning that 'B::run' will be discarded. As 'D::run' uses functions from both B and C I need to inherit from both classes.
I hope I have described it enough and not confused anybody.
Thanks for the help!
If you change B and C to virtually inherit from the A template class, they will share a single base instance when combined by D and this error will go away:
template<class I, class O>
class B : virtual public A<I,O> {
// ...
template<class I, class O, class M>
class C : virtual public A<I,O> {
However, this pattern (known as the diamond inheritance (anti-)pattern) can be very difficult to reason about and I would strongly suggest avoiding it if possible. You are likely to run into even more obscure problems later.
Here is a sample of this technique working, but showing some results that may not be expected at first glance:
class A {
public:
virtual void foo() = 0;
};
class B : virtual public A {
public:
virtual void foo() override;
};
void B::foo()
{
std::cout << "B::foo()" << std::endl;
}
class C : virtual public A { };
class D : public B, public C { };
int main() {
D d;
C & c = d;
c.foo();
return 0;
}
Note that even though you are calling C::foo(), which is pure virtual, since there is only one A instance the inherited pure virtual function resolves to B::foo() though the shared A vtable. This is a somewhat surprising side-effect -- that you can wind up invoking methods implemented on a cousin type.
The answer by #cdhowie gives you a solution.
To understand the problem the compiler is complaining about, take a set of simpler classes:
struct A
{
virtual void foo() = 0;
};
struct B : A
{
virtual void foo() {}
}
struct C : A
{
void bar() {}
}
struct D : B, C
{
};
The class hierarchy of D is:
A A
| |
B C
\ /
D
With this inheritance structure, D has two virtual tables, one corresponding to the B inheritance hierarchy and one corresponding to C inheritance hierarchy. The difference being that in the B hierarchy, there is an implementation of A::foo() while there isn't one in the C hierarchy.
Let's say you were allowed to construct an object of type D.
D d;
C* cp = &d;
Now cp points to the C hierarchy of D, and uses a virtual table in which foo is not implemented. That will be a run time error that the compiler is helping you avoid at compile time.
I know this is a late answer but since you are deriving from a pure virtual function for class C, you have to implement it, then in those functions you call the base class:
virtual void foo() const { // for class C
B::foo();
}

Compiler issue with pure virtual class and inheritance in C++

There is a compiler issue that I am facing. The code that I want to compile is as follows
#include <iostream>
class IA
{
public:
virtual void f1() = 0;
};
class A
{
public:
virtual void f1() { std::cout << "in A::f1" <<std::endl; }
};
class IB : public IA
{
public:
virtual void f3() = 0;
};
class B : public A, public IB
{
public:
// virtual void f1() { std::cout << "in B::f1" <<std::endl; }
virtual void f3() { std::cout << "in f3" <<std::endl; }
};
int main()
{
IB* b = new B();
b->f1();
b->f3();
std::cout << "Hello, world!\n";
}
Here, If I uncomment B::f1 things workout fine. The current code gives the following compiler error.
source_file.cpp: In function ‘int main()’:
source_file.cpp:32:20: error: cannot allocate an object of abstract type ‘B’
IB* b = new B();
^
source_file.cpp:23:7: note: because the following virtual functions are pure within ‘B’:
class B : public A, public IB
^
source_file.cpp:8:18: note: virtual void IA::f1()
virtual void f1() = 0;
The intent here is that the interface, IA, would be defined in the public headers of the library. The implementation class, A, would be done in the source code. All other classes would make use of this base class(A) to implement the publicly exposed abstract interface. Is this possible?
You should change
class A
to
class A : public IA
But it's not enough, as now you get multiple instances of IA in B. So you have to make the inheritance virtual:
class A : virtual public IA {...};
class IB : virtual public IA {...};
UPDATE But is there a real reason for IB to be inherited from IA? If no, drop it, and you won't need virtual inheritance:
class A : public IA {...};
class IB {...};
int main()
{
IB* b = new B();
// b->f1(); - You can't do it now, but do you really need to?
b->f3();
return 0;
}

multiple virtual inheritance in C++ complains on specific function call

In C++ multiple inheritance with virtual base
i understand why could this code be ambiguous , but why it still complains when i specifically call a derived class method ?
class A {
public:
virtual void f() { cout << 1 ;}
};
class B :virtual public A {
public:
virtual void f() { cout << 2; }
};
class C :virtual public A {
public:
virtual void f() { cout << 3; }
};
class D : public B, public C {};
void main(){
D* d = new D();
d->B::f();
getch();
}
i would expect that it will run the B:f() method but i get :
"ambiguous inheritance of 'void A::f(void)'
The problem is that your function is virtual which means it overrides address in vtable. You can't override one address with two functions.
Without virtual qualifier there would be just ambiguity during the call which can be avoided just like you did specifying base class B::f()
The problem is that your class D has two final overriders of function f. See http://en.cppreference.com/w/cpp/language/virtual about final overrider.