Multiple inheritance in c++ using abstract base classes [duplicate] - c++

I tried this code:
class A
{
virtual void foo() = 0;
};
class B
{
virtual void foo() = 0;
};
class C : public A, public B
{
//virtual void A::foo(){}
//virtual void B::foo(){}
virtual void A::foo();
virtual void B::foo();
};
void C::A::foo(){}
void C::B::foo(){}
int main()
{
C c;
return 0;
}
It is OK when using the commented part, but when I try to write the definitions outside the class declaration, the compiler reports errors.
I am using the MSVC11 compiler, does anyone know how to write this?
I need to move the code into the cpp file.
Thank you~~

A function overrides a virtual function of a base class based on the name and parameter types (see below). Therefore, your class C has two virtual functions foo, one inherited from each A and B. But a function void C::foo() overrides both:
[class.virtual]/2
If a virtual member function vf is declared in a class Base and in a class Derived, derived directly or indirectly from Base, a member function vf with the same name, parameter-type-list, cv-qualification, and ref-qualifier (or absence of same) as Base::vf is declared, then Derived::vf is also virtual (whether or not it is so declared) and it overrides Base::vf.
As I already stated in the comments, [dcl.meaning]/1 forbids the use of a qualified-id in the declaration of a (member) function:
When the declarator-id is qualified, the declaration shall refer to a previously declared member of the class or namespace to which the qualifier refers [...]"
Therefore any virtual void X::foo(); is illegal as a declaration inside C.
The code
class C : public A, public B
{
virtual void foo();
};
is the only way AFAIK to override foo, and it will override both A::foo and B::foo. There is no way to have two different overrides for A::foo and B::foo with different behaviour other than by introducing another layer of inheritance:
#include <iostream>
struct A
{
virtual void foo() = 0;
};
struct B
{
virtual void foo() = 0;
};
struct CA : A
{
virtual void foo() { std::cout << "A" << std::endl; }
};
struct CB : B
{
virtual void foo() { std::cout << "B" << std::endl; }
};
struct C : CA, CB {};
int main() {
C c;
//c.foo(); // ambiguous
A& a = c;
a.foo();
B& b = c;
b.foo();
}

You've got just one virtual function foo:
class A {
virtual void foo() = 0;
};
class B {
virtual void foo() = 0;
};
class C : public A, public B {
virtual void foo();
};
void C::foo(){}
void C::A::foo(){}
void C::B::foo(){};
int main() {
C c;
return 0;
}

I stepped into the same problem and accidentially opened a second thread. Sorry for that. One way that worked for me was to solve it without multiple inheritance.
#include <stdio.h>
class A
{
public:
virtual void foo(void) = 0;
};
class B
{
public:
virtual void foo(void) = 0;
};
class C
{
class IA: public A
{
virtual void foo(void)
{
printf("IA::foo()\r\n");
}
};
class IB: public B
{
virtual void foo(void)
{
printf("IB::foo()\r\n");
}
};
IA m_A;
IB m_B;
public:
A* GetA(void)
{
return(&m_A);
}
B* GetB(void)
{
return(&m_B);
}
};
The trick is to define classes derived from the interfaces (A and B) as local classes (IA and IB) instead of using multiple inheritance. Furthermore this approach also opens the option to have multiple realizations of each interface if desired which would not be possible using multiple inheritance.
The local classes IA and IB can be easily given access to class C, so the implementations of both interfaces IA and IB can share data.
Access of each interface can be done as follows:
main()
{
C test;
test.GetA()->foo();
test.GetB()->foo();
}
... and there is no ambiguity regarding the foo method any more.

You can resolve this ambiguity with different function parameters.
In real-world code, such virtual functions do something, so they usually already have either:
different parameters in A and B, or
different return values in A and B that you can turn into [out] parameters for the sake of solving this inheritance problem; otherwise
you need to add some tag parameters, which the optimizer will throw away.
(In my own code I usually find myself in case (1), sometimes in (2), never so far in (3).)
Your example is case (3) and would look like this:
class A
{
public:
struct tag_a { };
virtual void foo(tag_a) = 0;
};
class B
{
public:
struct tag_b { };
virtual void foo(tag_b) = 0;
};
class C : public A, public B
{
void foo(tag_a) override;
void foo(tag_b) override;
};

A slight improvement over adigostin's solution:
#include <iostream>
struct A {
virtual void foo() = 0;
};
struct B {
virtual void foo() = 0;
};
template <class T> struct Tagger : T {
struct tag {};
void foo() final { foo({}); }
virtual void foo(tag) = 0;
};
using A2 = Tagger<A>;
using B2 = Tagger<B>;
struct C : public A2, public B2 {
void foo(A2::tag) override { std::cout << "A" << std::endl; }
void foo(B2::tag) override { std::cout << "B" << std::endl; }
};
int main() {
C c;
A* pa = &c;
B* pb = &c;
pa->foo(); // A
pb->foo(); // B
return 0;
}
Assuming that the base classes A and B are given and cannot be modified.

Related

Overload a virtual method in a derived class so it takes more parameters in C++

I have an abstract class A with the pure virtual method void foo(int a) = 0
Then I have several classes that inherit from A and all of them define the method foo. But I need one of them, B, to make it so foo takes an extra parameter, int b, so sort of an overload.
Then I would like to do this:
A *bInstance = new B();
bInstance -> foo(1, 2);
But I get an error telling me that foo is taking too many parameters.
Writing this, I realize it's kind of a weird thing to do so maybe you can't do this and it's good that you can't do it. But in case it is possible, please do tell me how I should go about it.
You can use the overloaded function of B only if the pointer to use is of type B.
See:
#include <iostream>
#include <memory>
class A{
public:
virtual void foo(int a) = 0;
};
class B : public A
{
public:
virtual void foo(int a) override
{
}
void foo(int a, int b)
{
std::cout << a << "," << b;
}
};
int main(){
auto b = std::make_shared<B>();
b->foo(1, 2);
//to use a:
A* aPtr = b.get();
aPtr->foo(1);
return 0;
}
Although Bernd's answer is a possiblility, you must ask yourself what the effect of an overload is. E.g., think of the following.
std::unique_ptr<A> bAsA = std::make_unique<B>();
bAsA->foo(1, 2); // no worky.
bAsA->foo(1); // works, but what should it do?
It there's a different interface between A and B, I would suggest to add a layer of abstraction in form of a new base class (which I will call C).
So instead of
struct A {
// common
virtual void bar() {}
// class specific
virtual void foo(int) = 0;
};
struct B: public A {
// weird unused override which is still available
void foo(int) override {}
// class specific
void foo(int, int) {}
};
use
struct C {
// common
virtual void bar() {}
};
struct A: public C {
// class specific
virtual void foo(int) = 0;
};
struct B: public C {
// class specific
void foo(int, int) {}
};
You can fully achieve want you want using a default parameter:
class A
{
public:
virtual void foo(int a, int b = 0) = 0;
virtual ~A() = default;
};
class B : public A
{
public:
void foo(int a, int b) override { }
};
class C : public A
{
public:
void foo(int a, int b = 0) override { }
};
int main()
{
A* b = new B();
A* c = new C();
b->foo(1, 2);
c->foo(1);
}
You don't have to use this parameter in C::foo implementation (and any other derived classes) if you don't need to.

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();
}

How to deal with name hiding when base class function already overloaded with different access

Class foo act as interface, it has a pure virtual function and also provide some public overloaded function with same name for convenience so that derived class won't need to provide them in every implementation.
But since derived class must override the pure virtual function, it hides foo's public function.
I tried with "using foo::A", but it won't work because "using" will bring all function including the private one and result in compiler error "error C2876: 'foo' : not all overloads are accessible".
class foo
{
private:
virtual void A(int a)=0;
public:
void A()
{
A(1000);
}
void A(int a, int b)
{
A(a+b);
}
};
class bar : public foo
{
private:
virtual void A(int a)
{
cout << a << "\n";
}
};
int main()
{
bar x;
x.A();
return 0;
}
I know I can redefine every overloaded function in every class which derived from foo, but this defeat the purpose of convenience.
Or I can cast bar to foo before calling A(), but this approach will get confused since I need to remember which function is define in which class. For example:
class foo
{
private:
virtual void A(int a)=0;
public:
void A()
{
A(1000);
}
void A(int a, int b)
{
A(a+b);
}
};
class bar : public foo
{
private:
virtual void A(int a)
{
cout << "bar:" << a << "\n";
}
public:
void A(int a, int b, int c)
{
A(a+b+c);
}
};
class foobar : public bar
{
private:
virtual void A(int a)
{
cout << "foobar:" << a << "\n";
}
};
int main()
{
foobar x;
x.foo::A();
x.bar::A(1,2,3);
return 0;
}
I need to clearly remember A withouth argument come from foo, and A with three arguments come from bar. This is also not good for convenience.
When using the non virtual interface idiom, it's safer, and more explicit, to name the two functions (the public non-virtual and the private virtual) differently.
This shows well what the code does, and would solve your problem:
class foo
{
private:
virtual void doA(int a)=0;
public:
void A()
{
doA(1000);
}
void A(int a, int b)
{
doA(a+b);
}
};
And of course don't forget to change in the hierarchy.

Multiple virtual inheritance ambiguity

Probably best explained with an example:
struct A
{
virtual void foo() = 0;
};
struct B
{
virtual void foo() = 0;
};
struct C : A, B
{
// Implementation of A::foo
void A::foo();
// Implementation of B::foo
void B::foo();
};
// Define here; howto?
I'm aware I can define the functions inline with the class however that's not feasible in this instance (there are about 6 base classes to implement all with 40+ methods)
--
Apparently I wasn't clear enough. The question directly is: How to define both foo() methods that have been inherited without causing ambiguity issues?
The following does indeed work
void C::foo() { /* etc */ }
This will define the implementation of A::foo() yet what of B::foo() ? Bearing in mind I do not wish to define the methods within the declaration of C.
P.S., the reason for modelling the problem this way at all is predefined (COM/OLE)
--
This is fine (MSVC) albeit inline:
struct A { virtual int foo() = 0; };
struct B { virtual int foo() = 0; };
struct C : A, B
{
int A::foo() { return 1; }
int B::foo() { return 2; }
};
void main()
{
C* p = new C();
cout << ((A*) p)->foo();
cout << ((B*) p)->foo();
}
You can't provide separate overrides for two functions with the same signature defined in two base classes. (You can't define them inline within the class either, as you seem to think).
One possibility is to introduce intermediate base classes to rename the functions:
struct ABodge : A
{
void foo() {A_foo();}
virtual void A_foo() = 0;
};
struct BBodge : B
{
void foo() {B_foo();}
virtual void B_foo() = 0;
};
struct C : ABodge, BBodge
{
void A_foo();
void B_foo();
};
Alternatively, you could avoid multiple inheritance by composing two internal classes, each of which implement one of the base class interfaces:
class C
{
public:
// Could probably be defined as `operator A&()`, etc. to look more like
// inheritance, but I usually prefer conversions to be explicit.
A & asA() {return a;}
A const & asA() const {return a;}
B & asB() {return b;}
B const & asB() const {return b;}
private:
// These might need back-references to the 'C' that contains them.
struct AImpl : A {void foo();} a;
struct BImpl : B {void foo();} b;
};
Works as expected:
struct A { virtual void foo() = 0; };
struct B { virtual void foo() = 0; };
struct C : A, B { virtual void foo(); };
void C::foo() { }
For any C x;, static_cast<A&>(x).foo() and static_cast<B&>(x).foo() will call x.foo() as expected, which is precisely what the pure-virtual interfaces of A and B promise.

Virtual inheritance and static inheritance - mixing in C++

If you have something like this:
#include <iostream>
template<typename T> class A
{
public:
void func()
{
T::func();
}
};
class B : public A<B>
{
public:
virtual void func()
{
std::cout << "into func";
}
};
class C : public B
{
};
int main()
{
C c;
c.func();
return 0;
}
Is func() dynamically dispatched?
How could you implement class A such that if B has a virtual override, that it is dynamically dispatched, but statically dispatched if B doesn't?
Edit: My code didn't compile? Sorry guys. I'm kinda ill right now. My new code also doesn't compile, but that's part of the question. Also, this question is for me, not the faq.
#include <iostream>
template<typename T> class A
{
public:
void func()
{
T::func();
}
};
class B : public A<B>
{
public:
virtual void func()
{
std::cout << "in B::func()\n";
}
};
class C : public B
{
public:
virtual void func() {
std::cout << "in C::func()\n";
}
};
class D : public A<D> {
void func() {
std::cout << "in D::func()\n";
}
};
class E : public D {
void func() {
std::cout << "in E::func()\n";
}
};
int main()
{
C c;
c.func();
A<B>& ref = c;
ref.func(); // Invokes dynamic lookup, as B declared itself virtual
A<D>* ptr = new E;
ptr->func(); // Calls D::func statically as D did not declare itself virtual
std::cin.get();
return 0;
}
visual studio 2010\projects\temp\temp\main.cpp(8): error C2352: 'B::func' : illegal call of non-static member function
visual studio 2010\projects\temp\temp\main.cpp(15) : see declaration of 'B::func'
visual studio 2010\projects\temp\temp\main.cpp(7) : while compiling class template member function 'void A<T>::func(void)'
with
[
T=B
]
visual studio 2010\projects\temp\temp\main.cpp(13) : see reference to class template instantiation 'A<T>' being compiled
with
[
T=B
]
I'm not sure I understand what you're asking, but it appears you are missing the essential CRTP cast:
template<class T>
struct A {
void func() {
T& self = *static_cast<T*>(this); // CRTP cast
self.func();
}
};
struct V : A<V> { // B for the case of virtual func
virtual void func() {
std::cout << "V::func\n";
}
};
struct NV : A<NV> { // B for the case of non-virtual func
void func() {
std::cout << "NV::func\n";
}
};
If T does not declare its own func, this will be infinite recursion as self.func will find A<T>::func. This is true even if a derived class of T (e.g. DV below) declares its own func but T does not.
Test with different final overrider to show dispatch works as advertised:
struct DV : V {
virtual void func() {
std::cout << "DV::func\n";
}
};
struct DNV : NV {
void func() {
std::cout << "DNV::func\n";
}
};
template<class B>
void call(A<B>& a) {
a.func(); // always calls A<T>::func
}
int main() {
DV dv;
call(dv); // uses virtual dispatch, finds DV::func
DNV dnv;
call(dnv); // no virtual dispatch, finds NV::func
return 0;
}
How could you implement class A such that if B has a virtual override, that it is dynamically dispatched, but statically dispatched if B doesn't?
Somewhat contradictory, isn't it? A user of class A may know nothing about B or C. If you have a reference to an A, the only way to know if func() needs dynamic dispatch is to consult the vtable. Since A::func() is not virtual there is no entry for it and thus nowhere to put the information. Once you make it virtual you're consulting the vtable and it's dynamic dispatch.
The only way to get direct function calls (or inlines) would be with non-virtual functions and no indirection through base class pointers.
Edit: I think the idiom for this in Scala would be class C: public B, public A<C> (repeating the trait with the child class) but this does not work in C++ because it makes the members of A<T> ambiguous in C.
In your particular example, there's no need for dynamic dispatch because the type of c is known at compile time. The call to B::func will be hard coded.
If you were calling func through a B*, then you would be calling a virtual function. But in your highly contrived example, that would get you to B::func once again.
It doesn't make much sense to talk about dynamic dispatch from an A* since A is a template class - you can't make a generic A, only one that is bound to a particular subclass.
How could you implement class A such that if B has a virtual override, that it is dynamically dispatched, but statically dispatched if B doesn't?
As others have noticed, it's really hard to make sense of that question, but it made me remember something I have learned a long time ago, so here's a very long shot at answering your question:
template<typename Base> class A : private Base
{
public:
void func()
{
std::count << "A::func";
}
};
Given this, it depends on A's base whether func() is virtual. If Base declares it virtual then it will be virtual in A, too. Otherwise it won't. See this:
class V
{
public:
virtual void func() {}
};
class NV
{
};
class B : public A<V> // makes func() virtual
{
public:
void func()
{
std::count << "B::func";
}
};
class C : public A<NV> // makes func() non-virtual
{
public:
void func()
{
std::count << "C::func";
}
};
Would this happen to answer your question?
Whether the function is dynamically dispatched or not depends on two things:
a) whether the object expression is a reference or pointer type
b) whether the function (to which overload resolution resolves to) is virtual or not.
Coming to your code now:
C c;
c.func(); // object expression is not of pointer/reference type.
// So static binding
A <B> & ref = c;
ref.func(); // object expression is of reference type, but func is
// not virtual. So static binding
A<D>* ptr = new D;
ptr->func(); // object expression is of pointer type, but func is not
// virtual. So static binding
So in short, 'func' is not dynamically dispatched.
Note that :: suppresses virtual function call mechanism.
$10.3/12- "Explicit qualification with
the scope operator (5.1) suppresses
the virtual "call mechanism.
The code in OP2 gives error because the syntax X::Y can be used to invoke 'Y' in the scope of 'X' only if 'Y' is a static member in the scope of 'X'.
Seems you just had to add a little trace and usage to answer your own question...
#include <iostream>
template<typename T> struct A {
void func() {
T::func();
}
};
struct B1 : A<B1> {
virtual void func() {
std::cout << "virtual void B1::func();\n";
}
};
struct B2 : A<B2> {
void func() {
std::cout << "void B2::func();\n";
}
};
struct C1 : B1 { };
struct C2 : B2 { };
struct C1a : B1 {
virtual void func() {
std::cout << "virtual void C1a::func();\n";
}
};
struct C2a : B2 {
virtual void func() {
std::cout << "virtual void C2a::func();\n";
}
};
int main()
{
C1 c1;
c1.func();
C2 c2;
c2.func();
B1* p_B1 = new C1a;
p_B1->func();
B2* p_B2 = new C2a;
p_B2->func();
}
Output:
virtual void B1::func();
void B2::func();
virtual void C1a::func();
void B2::func();
Conclusion: A does take on the virtual-ness of B's func.