派生類向基類轉換的可訪問性的我的理解

派生類向基類的轉換是否可訪問由使用該轉換的代碼決定 , 同時派生類的派生訪問說明符也會有影響. 假定D繼承自B:ios

1           只有當D公有繼承B時 , 用戶代碼才能使用派生類向基類的轉換;若是D繼承B的方式是受到保護的或者是私有的 , 則用戶代碼不能使用該轉換.ide

2           不論D以什麼方式繼承B , D的成員函數和友元都能使用派生類向基類的轉換; 派生類向其直接基類的類型轉換對於派生類的成員和友元來講永遠是可訪問的.函數

3           若是D繼承B的方式是公有的或者受保護的 , 則D的派生類的成員和友元可使用D向B的類型轉換; 反之 , 若是D繼承B的方式是私有的 , 則不能使用.this

以上節選自C++ Primer P544頁spa

因爲第一次讀到的時候感受很是的難以理解 , 所以記錄下我的的理解 , 防止本身忘記 , 文中的代碼編譯環境爲VS2017指針

第一條的我的理解 :

只有當D公有繼承B時 , 用戶代碼才能使用派生類向基類的轉換;若是D繼承B的方式是受到保護的或者是私有的 , 則用戶代碼不能使用該轉換.code

我的理解: 當派生類以共有方式繼承基類時 , 纔可使用基類指針指向派生類來操縱 . 而其餘兩種繼承方式是失敗的 . 因此一個結論即便是發生多態時 , 也必須是公有繼承時 , 基類指針才能夠指向派生類對象

代碼示例 :blog

 1 //只有公有繼承時 , 基類指針或引用才能夠指向派生類對象 , 再發生多態時 ,一樣有效
 2 #pragma warning (disable:4996)
 3 #include <iostream>
 4 
 5 class Base
 6 {
 7 public:
 8     virtual void memPublic() { std::cout << "Base公有成員被調用" << std::endl; }
 9 protected:
10     void memProtected() { std::cout << "Base保護成員被調用" << std::endl; }
11 private:
12     void memPrivate() { std::cout << "Base私有成員被調用" << std::endl; }
13 };
14 
15 class Derive :public Base
16 {
17 public:
18     virtual void memPublic() override{ std::cout << "Derive公有成員被調用" << std::endl; }
19     void memPri() 
20     { 
21         this->Base::memProtected();
22         this->memPublic();
23         std::cout << "Derive的我的函數" << std::endl;
24     }
25 };
26 class Derive_pro : protected Base
27 {
28 public:
29     virtual void memPublic() override { std::cout << "Derive_pro公有成員被調用" << std::endl; }
30 };
31 class Derive_pri : private Base
32 {
33 public:
34     virtual void memPublic() override { std::cout << "Derive_pri公有成員被調用" << std::endl; }
35 };
36 
37 int main()
38 {
39     std::cout << "--派生類--" << std::endl;
40     Base * dev = new Derive;
41     //Base * dev2 = new Derive_pro;//error 編譯器報錯, 不容許對不可訪問的基類的轉換
42     //Base * dev3 = new Derive_pri;//error 編譯器報錯, 不容許對不可訪問的基類的轉換
43 
44     system("pause");
45     return 0;
46 }

 

第二條的我的理解 :

在理解第二條前 , 首先應該明白一句話 , 一樣節選自C++ Primer5 P544頁繼承

派生訪問說明符對於派生類的成員及友元可否訪問其直接基類的成員沒有什麼影響 .對基類成員的訪問權限只與基類中的訪問說明符有關

這句話的含義 , 能夠理解爲不同的繼承方式影響的是派生類的對象對於基類成員的的訪問權限 , 而對於派生類內部 (派生類的成員函數中) 對基類成員的訪問權限無關.

也就是說不管是公有繼承仍是私有繼承 , 保護繼承 , 在派生類的內部一樣能夠訪問基類的公有成員和保護成員

那麼接下來開始理解第二條

不論D以什麼方式繼承B , D的成員函數和友元都能使用派生類向基類的轉換; 派生類向其直接基類的類型轉換對於派生類的成員和友元來講永遠是可訪問的.

什麼含義已經很顯而易見了 , 不管派生類對於基類的繼承方式是什麼 , 派生類的成員和友元永遠都有對於基類的的保護成員和公有成員的訪問權限  , 這裏須要注意的是派生類的成員和友元限於派生類內 , 而不是派生類的對象

代碼示例 :

 1 //代碼中只對私有繼承進行了展現 , 能夠看出私有繼承時 , 並不影響派生類中訪問基類的共有成員和保護成員
 2 class Base
 3 {
 4 public:
 5     int base_public;
 6 protected:
 7     int base_protect;
 8 private:
 9     int base_private;
10 };
11 
12 class Derive :private Base
13 {
14 public:
15     int dev1 = base_public;
16     int dev2 = base_protect;
17     //int dev3 = base_private; //error , 編譯器警告成員不可訪問
18 };

 

第三條 :

若是D繼承B的方式是公有的或者受保護的 , 則D的派生類的成員和友元可使用D向B的類型轉換; 反之 , 若是D繼承B的方式是私有的 , 則不能使用.

理解方式參考第二條 , 第三條並非第二條的悖論 , 由於這句話有一個關鍵字 "D的派生類的成員" , 因此本意爲

當派生類以公有和保護的方式繼承基類時 , 則派生類的派生類的成員(就是類的內部)和友元才擁有能夠訪問基類的保護和公有成員的權限 , 而若是是私有的 , 這顯然不能夠 , 由於基類的全部成員已經變爲派生類的私有成員  , 因此派生類的派生類並不能訪問他們.