【问题标题】:Implementing interfaces in C++ with inherited concrete classes使用继承的具体类在 C++ 中实现接口
【发布时间】:2012-02-22 23:27:01
【问题描述】:

我正在尝试使用抽象类在 C++ 中定义接口类型并使用具体类来实现它们。我遇到的问题是我不能从另一个接口继承和接口,也不能从基具体类继承实现。

我的目标是能够定义可以从不太复杂的基本接口继承的接口层次结构。我还希望能够通过从具体类继承来扩展接口的实现(例如从下面示例中的 TObjectA 继承)。

这就是我所拥有的。我得到的错误是“不允许抽象类类型“TObjectB”的对象”。我相信我知道为什么,那是因为我没有在 TObjectB 中实现 MethodA()。但我真正想要的是由基类(TObjectA)提供实现,并且仍然具有接口层次结构(IInterfaceB 继承自 IInterfaceA)。我也不想在派生的 concreate 类中重复所有继承的接口方法。我该怎么做?

class IInterfaceA 
{ 
public:
    virtual void MethodA() = 0; 
}; 

class IInterfaceB : IInterfaceA
{ 
public:
    virtual void MethodB() = 0; 
}; 

class TObjectA : public IInterfaceA 
{ 
public:
    void MethodA() { cout << "Method A"; }  
}; 

class TObjectB : public TObjectA, public IInterfaceB 
{ 
public:
    void MethodB() { cout << "Method B"; } 
}; 

void TestInterfaces()
{
    IInterfaceB* b = new TObjectB(); // error: object of abstract class type "TObjectB" is not allowed
    b->MethodB();
    delete b;
}

【问题讨论】:

  • 您需要虚拟基类。例如。 see here

标签: c++ inheritance multiple-inheritance


【解决方案1】:

在您的类层次结构中,TObjectB 实际上有两个IInterfaceA 基类子对象:一个通过IInterfaceB 继承,一个通过TObjectA 继承。他们每个人的MethodA() 都需要实现。

您需要使用公共虚拟继承从接口类继承,这样可以确保每个接口类类型只有一个基类子对象:

class IInterfaceA 
{ 
public:
    virtual void MethodA() = 0; 
}; 

class IInterfaceB : public virtual IInterfaceA
{ 
public:
    virtual void MethodB() = 0; 
}; 

class TObjectA : public virtual IInterfaceA 
{ 
public:
    void MethodA() { cout << "Method A"; }  
}; 

class TObjectB : public TObjectA, public virtual IInterfaceB 
{ 
public:
    void MethodB() { cout << "Method B"; } 
}; 

void TestInterfaces()
{
    TObjectB b_object;
    IInterfaceB& b = b_object;
    b.MethodB();
}

这种复杂的类层次结构是否可取完全是另一回事。

【讨论】:

  • 当我使用您的代码时,我收到以下警告“警告:'TObjectB':通过支配继承 'TObjectA::TObjectA::MethodA'”。此外,当我将测试更改为使用堆分配的对象时,我得到一个运行时断言错误并且执行停止: void TestInterfaces() { IInterfaceB* b = new TObjectB(); b->方法B();删除 b; }
  • 如果你打算通过它们多态地删除对象,你的接口类必须有虚拟析构函数。至于警告:避免复杂的继承层次结构。
【解决方案2】:

您的问题是由可怕的钻石继承引起的。你已经实现了TObjectA::IInterfaceA::MethodA,但没有实现IInterfaceB::IInterfaceA::MethodA

我的建议是让 IIterfaceA 和 IIterfaceB 完全独立。如果这不可行,您可以查看虚拟继承。

【讨论】:

    猜你喜欢
    • 2016-03-07
    • 2019-01-05
    • 2021-03-17
    • 1970-01-01
    • 2022-01-23
    • 1970-01-01
    • 2023-03-25
    • 2016-10-23
    • 2019-05-10
    相关资源
    最近更新 更多