參考 effective c++ 條款33
我覺得看完書中的 總結一下
感覺就是在講作用域的規則,在繼承中作用域的規則
編譯器查找同名變量函數的規則
double num = 5; //global 變量
int main()
{
int num = 3; //local 變量
cout << num << endl;
}
運行結果大家都知道是 3
編譯器在局部函數 main 內 首先尋找 名字爲 num 的變量
如果找不到 就去外層作用域繼續找 還找不到就找有沒有 global
c++ 名稱遮掩規則 所做的唯一事件就是遮掩名稱
這個名稱變量的類型是否相同並不重要 上面就是 int num 遮掩了 double num
上面比較直觀簡單 向下遞增難度講講
繼承中的遮掩名稱
看一下這個繼承結構
基類 實現了3個 函數
- 純虛函數 mf1()
- 虛函數 mf2()
- 普通函數mf3()
派生類 重新實現了 純虛函數 mf1()
實現了自己的函數 mf4()
mf4() 中 又調用了 mf2()
當編譯器執行到 mf4 中時 看到 mf2 要知道他是啥東西
- 先在 local 函數 mf4() 作用域內找有沒有 mf2()
- 在去Derived 中 找有沒有 mf2()
- 在去Derived 的父類中 繼續找有沒有 mf2()
- . . . . . .
- 繼續向外層找 找不到就報錯了 說沒有 mf2()
繼續增加難度 繼承中出現重載
仔細看上面的規則
int x = 1;
Derived d;
d.mf1();
d.mf1(x);
d.mf2();
d.mf3();
d.mf3(x);
這段代碼執行會發生什麼呢?
報錯了 說明 d.mf1(int) 和 d.mf3(double) 繼承失敗了
什麼原因呢?
編譯器 不管你的函數是不是虛函數 是不是重載
因爲編譯器在查找名字時,並沒有“爲重載而走的很遠”,C++的確是支持重載的,編譯器在發現函數重載時,會去尋找相同函數名中最爲匹配的一個函數(從形參個數,形參類型兩個方面考慮,與返回值沒有關係),如果大家的匹配程度都差不多,那麼編譯器會報歧義的錯。
首先找 作用域內 mf1() 和 mf3 有沒有同名的 如果有 那麼就不會去上層找了
也就是說 重載的帶參的 base mf1(int) 和 mf3(double) 被 derived class 內的 mf1() 和 mf3() 給 遮掩掉了
我現在就要調用父類重載的函數 現在有兩種辦法解決這個問題
1.採用 using 聲明
用了using,實際上是告訴編譯器,把父類的那個函數也納入第一批查找範圍裏面,這樣就能發現匹配得更好的重載函數了。
這樣就不報錯了 當查找 mf1 時 編譯器發現兩個就會按照重載函數的規則執行。
2.採用 inline 轉交函數
也重載一個 帶 int 的 mf1(int x) 函數
然後內部實現時 調用基類的 函數 就完成了 我們想要的的效果了