子類所繼承的兩個父類有同名純虛函數,怎麼辦?

子類所繼承的兩個父類有同名純虛函數,怎麼辦?

返回值,參數類型全都一樣.怎麼辦? 謝謝!

例如:

struct Base1
{
virtual void fun()=0;
};

struct Base2
{
virtual void fun()=0;
};

struct child : Base1 , Base2
{
virtual void fun() override {}
//這到底是實現了Base1::fun還是Base2::fun?
//我想兩個分別實現怎麼辦?
};


這裡有好幾種情況:

首先,child裡面什麼都不寫,但是又要去調用child中的fun。

其次,child寫了,那就一切正常。

再次,如果child中你不實現,但是使用了作用域限定表達式,或者讓虛函數在Base1上起作用,那也沒有問題。


你要辦什麼。想override就override好了咯。又沒影響。


總覺得這種情況應該去改兩個父類……

不能直接改兩個父類的源碼的話,那你可以建兩個virtual wrapper class分別繼承兩個父類,然後把這個相同的函數隱藏起來……然後再繼承兩個wrapper

不過說到底多繼承就是邪道啊!!


//這到底是實現了Base1::fun還是Base2::fun?
這是覆蓋掉了,跟父類的實現沒關係了
//我想兩個分別實現怎麼辦?
完全相同的簽名,做不到啊


估計題主擔心的是這樣會不會衝突或者可不可以這樣用。這樣做是可以的,子類的func()覆蓋掉了兩個父類的同名虛函數,「子類關於父類的兩個虛表對應func()的位置上存儲的都是子類func()的成員方法地址」,這只是籠統的說法,不同的編譯器具體的細節可能不同。題主可以從itanium c++ ABI或者gcc的技術文檔中查到相關資料。

另外,誰讓C++有多繼承這種鬼呢!


如果你在Child子類重寫fun(),效果是相當於同時重寫了Base1::fun()和Base2::fun()。

本來C++的標準里是要添加一個特性來避免這種情況的,但是設計者們認為這種情形很罕見,不值得為此添加額外的特性。

而且從類設計的角度來看,如果兩個介面有一樣的方法,那麼他們的行為也應該是一樣的。

如果要避免,那麼應該這樣:

struct Base1
{
virtual void fun1()=0;
};

struct Base2
{
virtual void fun2()=0;
};

struct child : Base1 , Base2
{
virtual void fun1() override {} // 重寫Base1::fun1()
virtual void fun2() override {} // 重寫Base2::fun2()

};

順便說下,在VC++中,我發現還可以這樣做:

struct Base1
{
virtual void fun()=0;
};

struct Base2
{
virtual void fun()=0;
};

struct child : Base1 , Base2
{
virtual void Base1::fun() override {} // 重寫Base1::fun()
virtual void Base2::fun() override {} // 重寫Base2::fun()

};

注意Base1::fun()和Base2::fun()必須是純虛函數。

尚不清楚這個是VC++的擴展還是新的標準。


兩個都要實現可以這樣,不過只能放在類內。

class Child
: public Base1
, public Base2
{
public:
void Base1::func() override
{
}

void Base2::func() override
{
}
};


應該是兩個父類虛函數都會覆蓋吧


推薦閱讀:

為什麼GCC5.x.x版本中的std::string不再採用寫時複製的實現,而改用了SSO的實現?
如何用 C/C++ 求 1 到 1000 內的所有完全數?
reinterpret_cast把const string*轉換成const char*出錯?
為什麼用了using namespace std會報錯?
c++如何在編譯期判斷一個對象是否是字元串字面值?

TAG:面向對象編程 | C |