Laura 建议的虚拟继承当然是解决问题的方法。但它最终不会只有一个InterfaceA。例如,它也有“副作用”。见https://isocpp.org/wiki/faq/multiple-inheritance#mi-delegate-to-sister。但如果习惯了,它可能会派上用场。
如果你不想要副作用,你可以使用模板:
struct InterfaceA
{
virtual void methodA() = 0;
};
template<class IA>
struct ClassA : public IA //IA is expected to extend InterfaceA
{
void methodA() { 5+1;}
};
struct InterfaceB : public InterfaceA
{
virtual void methodB() = 0;
};
struct ClassAB
: public ClassA<InterfaceB>
{
void methodB() {}
};
int main()
{
InterfaceB* test = new ClassAB();
test->methodA();
}
所以,我们只有一个父类。
但是当有多个“共享”类时,它看起来更难看(InterfaceA 是“共享的”,因为它位于“可怕的钻石”之上,请参见此处 https://isocpp.org/wiki/faq/multiple-inheritance 由 Laura 发布)。查看示例(如果 ClassA 也实现了 interfaceC,将会是什么):
struct InterfaceC
{
virtual void methodC() = 0;
};
struct InterfaceD : public InterfaceC
{
virtual void methodD() = 0;
};
template<class IA, class IC>
struct ClassA
: public IA //IA is expected to extend InterfaceA
, public IC //IC is expected to extend InterfaceC
{
void methodA() { 5+1;}
void methodC() { 1+2; }
};
struct InterfaceB : public InterfaceA
{
virtual void methodB() = 0;
};
struct ClassAB
: public ClassA<InterfaceB, InterfaceC> //we had to modify existing ClassAB!
{
void methodB() {}
};
struct ClassBD //new class, which needs ClassA to implement InterfaceD partially
: public ClassA<InterfaceB, InterfaceD>
{
void methodB() {}
void methodD() {}
};
不好的是,您需要修改现有的 ClassAB。但是你可以写:
template<class IA, class IC = interfaceC>
struct ClassA
那么ClassAB保持不变:
struct ClassAB
: public ClassA<InterfaceB>
而且你有模板参数 IC 的默认实现。
使用哪种方式由您决定。我更喜欢模板,因为它很容易理解。很难养成习惯, B::incrementAndPrint() 和 C::incrementAndPrint() 将打印不同的值(不是您的示例),请参见:
class A
{
public:
void incrementAndPrint() { cout<<"A have "<<n<<endl; ++n; }
A() : n(0) {}
private:
int n;
};
class B
: public virtual A
{};
class C
: public virtual A
{};
class D
: public B
: public C
{
public:
void printContents()
{
B::incrementAndPrint();
C::incrementAndPrint();
}
};
int main()
{
D d;
d.printContents();
}
还有输出:
A have 0
A have 1