effective c++條款33:避免遮掩繼承而來的名稱
阿新 • • 發佈:2018-11-11
1. using
考慮下面程式:
#include <iostream> using namespace std; class Based { public: void Func() { cout << "Base" << endl; } int Func(int x){} }; class Derived : public Based { public: int Func() { cout << "Derived" << endl; } }; int main() { Derived D; D.Func(3); return 0; }
我們發現該程式是無法通過編譯器的,因為編譯器查詢名稱的規則是:
首先查詢當前作用域內是否有相同的名稱,如果有,無論型別是否匹配都不再進行查詢,如果沒有再向上一級作用域查詢。
在該例中,語句D.Func(3)會使編譯器首先查詢當前作用域也就是Derived中有沒有名稱Func,找到之後雖然函式型別不匹配但是不再向上查詢,所以無法呼叫父類中的相應的過載函式(注意:子類的作用域包含在父類的作用域之中)。
解決方案:在子類中利用using使父類中的內容子類可見:
#include <iostream> using namespace std; class Based { public: void Func() { cout << "Base" << endl; } int Func(int x){} }; class Derived : public Based { public: using Based::Func; int Func() { cout << "Derived" << endl; } }; int main() { Derived D; D.Func(3); return 0; }
這樣,我們就可以使用父類中的過載函數了。
2. 轉交函式
在某些情況下,你可能不想繼承父類中的所有函式,當然,這不可能發生在public繼承中,因為public繼承需要滿足is-a模型,但是在private繼承中確是有意義的。
我們不能再次使用using,因為using會使父類中所有的同名函式可見,我們需要一個轉交函式:
#include <iostream> using namespace std; class Based { public: void Func() { cout << "Base" << endl; } int Func(int x){} }; class Derived : private Based { public: void Func()//轉交函式 { Based::Func(); } };
這樣,我們就可以選擇部分繼承而不是全部繼承。
總結:
如果你想全部繼承而且還要過載,那麼就在子類中使用using,如果你想部分繼承,那麼就在子類中使用轉交函式。