2012-02-22 57 views
9

我想在C++中使用抽象類定義接口類型,並用具體類實現它們。我遇到的問題是我不能從另一個接口繼承和接口,並從基礎具體類繼承實現。在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; 
} 
+2

您需要虛擬基類。例如。 [see here](http://stackoverflow.com/questions/4605556/when-virtual-inheritance-is-a-good-design/4606206#4606206) – 2012-02-22 23:33:20

回答

11

在你的類層次結構,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(); 
} 

無論這樣的複雜的類層次結構合意的是另一件事。

+0

當我使用你的代碼時,我得到下面的警告「Warning:' TObjectB':通過優勢繼承'TObjectA :: TObjectA :: MethodA'。 此外,當我改變測試使用堆分配的對象我得到一個運行斷言錯誤和執行停止: 空隙TestInterfaces() { IInterfaceB * B =新TObjectB();方法B(); 刪除b; } – sysrpl 2012-02-22 23:45:03

+0

如果您打算通過它們多態刪除對象,則您的接口類必須具有虛擬析構函數。至於警告:避免複雜的繼承層次結構。 – 2012-02-23 00:02:50

1

你的問題是由可怕的鑽石繼承造成的。您已實施TObjectA::IInterfaceA::MethodA,但不是IInterfaceB::IInterfaceA::MethodA

我的建議是讓IIterfaceA和IIterfaceB完全獨立。如果這是不可能的,你可以看看虛擬繼承。