Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ multiple inheritance function name collision

Tags:

c++

oop

templates

Context: I was discussing C# vs. Java at work when the following question came up, and I wondered how (or if) it could be elegantly resolved in C++.

Let's say you have two classes A and B (whose details are not important) and then two templated class G and H described as something like:

template <typename T>            | template <typename T> 
class G                          | class H
{                                | {
   public :                      |    public :
      T * foo() ;                |       virtual T * foo() = 0 ;
      // etc.                    |       // etc.
} ;                              | } ;

Then we have the class C and D described like:

class A { /* ... */ } ;
class B { /* ... */ } ;

class C : public G<A>, public G<B>
{
} ;

class D : public H<A>, public H<B>
{
   // ???
} ;

I want to be able to call for C the method foo from G<A> and foo from G<B>. And I want to be able to override for D the method foo from H<A> and H<B>.

In the end, I want to be able to use C and D like in the following examples:

C c ;
A * a = c.??? ; (I want to call G<A>::foo())
B * b = c.??? ; (I want to call G<B>::foo())

D d ;
A * a = c.??? ; (I want to call H<A>::foo())
B * b = c.??? ; (I want to call H<B>::foo())

There always are ways to do it (and I have some ideas), but I'm interested a list of elegant and safe ways to do it, including pros/cons.

So, how would you do it?

like image 329
paercebal Avatar asked Jun 20 '26 20:06

paercebal


2 Answers

The two ways I can think of:

C x;

x.G<A>::foo(); // 1
static_cast<G<A>&>(x).foo(); // 2

That is: either explicitly qualifying the function’s name, or upcast in the type hierarchy.

like image 137
Konrad Rudolph Avatar answered Jun 22 '26 09:06

Konrad Rudolph


How about, overloading and using different arguments :

template <typename T>
class G
{
public:
    T * foo(T &a) {/* ... */};
    // etc.
};

class A
{
public:
    /* ... */
};

class B
{
    public:
    /* ... */
};

class C : public G<A>, public G<B>
{
public:
    using G<A>::foo;
    using G<B>::foo;

};

int main()
{
    C c;

    A a;
    B b;

    c.foo(a);
    c.foo(b);

    return 0;
}
like image 38
masoud Avatar answered Jun 22 '26 10:06

masoud



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!