c++ 避免遮掩繼承而來的名稱

參考 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) 函數
然後內部實現時 調用基類的 函數 就完成了 我們想要的的效果了

注意:

1.派生類的名稱會遮掩基類的名稱,在public繼承下從來沒有人希望如此
2.可以用 using 聲明 或者 轉交函數 解決這個問題
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章