I have a situation with some libraries I am using whereby there is an ambiguity with the function to be called due to multiple inheritance and namespaces. The following (very contrived) example shows it. In C::c(), I want to call the f() from N1::B, but I can't work out how to do it. Gcc repoprts the following errors for my three attempts at making the call. Clang reports very similar errors. Does anybody have any ideas on how to do it please?
namespace N1
{
class B
{
protected:
void f();
};
}
namespace N2
{
class B
{
protected:
void f();
};
}
class B1 : public N1::B, public N2::B
{
};
class B2 : public N1::B, public N2::B
{
};
class C : public B1, public B2
{
void c();
};
void
C::c()
{
N1::B::f();
B1::N1::B::f();
static_cast<B1*>(this)->N1::B::f();
}
1 2 3 4 5
z.cpp: In member function âvoid C::c()â:
z.cpp:35: error: cannot call member function âvoid N1::B::f()â without object
z.cpp:36: error: âclass B1::N1â has not been declared
z.cpp:6: error: âvoid N1::B::f()â is protected
z.cpp:37: error: within this context
I think the problem is that your B1 and B2 classes each inherit from N1 and N2's Bs, so there are multiple copies of N1::B and N2::B inside a C object. So when you want to call N1::B::f(), it doesn't know whether to call the one inside of B1 or B2.
Try making the B1 and B2 classes virtually inherit from the namespace classes and see if that changes things.
Nicely contrived.
Any reason virtual inheritance is not used? It would both solve the ambiguity and cut down on the useless copies of the base classes in every instance of B1, B2, or C.
Like I said, the problem is the base classes come from 3rd-party libraries - unfortunately, I have no control over them. So I can't redesign them to do virtual inheritance.
naraku: They aren't static and I'm not calling them as if they are: C derives from them so it can call them like I'm doing.
#include <iostream>
// ************ classes defined by the libray *****************
namespace N1
{
class B
{
public: virtual ~B() {}
protected: virtualvoid f()
{ std::cout << "N1::B::f() this: " << this << '\n' ; }
// ...
} ;
}
namespace N2
{
class B
{
public: virtual ~B() {}
protected: virtualvoid f()
{ std::cout << "N2::B::f() this: " << this << '\n' ; }
// ...
} ;
}
class B1 : public N1::B, public N2::B { /* ... */ } ;
class B2 : public N1::B, public N2::B { /* ... */ } ;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
// ************ interfacew classes defined by us *****************
class B1_ : public B1 // interfacve class to resolve ambiguity
{
protected:
virtualvoid n1_b1_f() { N1::B::f() ; }
virtualvoid n2_b1_f() { N2::B::f() ; }
};
class B2_ : public B2 // interfacve class to resolve ambiguity
{
protected:
virtualvoid n1_b2_f() { N1::B::f() ; }
virtualvoid n2_b2_f() { N2::B::f() ; }
};
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
// ********* inherit via the interface classes *************
class C : public B1_, public B2_ // inherit from interfacve classes
{
public: void c()
{
n1_b1_f() ;
n1_b2_f() ;
n2_b1_f() ;
n2_b2_f() ;
}
};
int main()
{
C cc ;
cc.c() ;
}