成員訪問控制
在c++中,類的成員訪問控制分為公有public,保護protected,私有private。其訪問許可權物件分為類成員函式和使用者(類的例項化或物件),派生類後面討論。不管是公有,保護還是私有,自身類的成員函式都可以直接訪問(「自身類」是為了區分後面的派生類)。但是使用者(類的物件)只能訪問公有成員,保護成員和私有成員都不能訪問。
比如:
// 定義乙個類
class
cmyclass
// 沒問題,可以訪問保護成員
intgetmem()
// 沒問題,可以訪問私有成員
intgetmem()
public
:int m_public;
// 公有成員變數
protected
:int m_protect;
// 保護成員變數
private
:int m_private;
// 私有成員變數};
// 例項化類的物件
cmyclass obj;
obj.m_public =1;
// 沒問題,使用者可以訪問公有成員
obj.m_protect =1;
// 錯誤,使用者不可以訪問保護成員
obj.m_private =1;
// 錯誤,使用者不可以訪問私有成員
繼承分類現在來討論一下派生類的派生訪問說明符,同樣包括公有繼承public,保護繼承protected和私有繼承private。這些派生訪問說明符對派生類本身沒有任何影響,無論是哪種繼承派生類本身都只能訪問基類的公有成員和保護成員,不能訪問基類的私有成員。這些派生訪問說明符是用於控制派生類使用者(派生類物件)對基類成員的訪問許可權。
比如:
// 定義乙個基類
class
base
;// 公有繼承派生類
class
derived_public
:public
base
// 沒問題,可以訪問基類保護成員
intgetprotect()
// 錯誤,不可以訪問基類私有成員
intgetprivate()
};// 保護繼承派生類
class
derived_protect
:protected
base
// 沒問題,可以訪問基類保護成員
intgetprotect()
// 錯誤,不可以訪問基類私有成員
intgetprivate()
};// 私有繼承派生類
class
derived_private
:private
base
// 沒問題,可以訪問基類保護成員
intgetprotect()
// 錯誤,不可以訪問基類私有成員
intgetprivate()
};
從上面可以看到無論是哪種方式繼承,派生類類本身都是只能訪問基類的公有和保護成員,不能訪問私有成員。下面看一下派生訪問說明怎麼限制使用者(派生類的物件):
// 定義乙個公有繼承的派生類物件
derived_public pub;
// 沒問題,公有繼承的派生類物件可以訪問基類的公有成員
pub.m_public =1;
// 錯誤,公有繼承的派生類物件不可以訪問基類的保護成員
pub.m_protect =1;
// 錯誤,公有繼承的派生類物件不可以訪問基類的私有成員
pub.m_private =
1;
// 定義乙個保護繼承的派生類物件
derived_protect prot;
// 錯誤,保護繼承的派生類物件不可以訪問基類的公有成員
prot.m_public =1;
// 錯誤,保護繼承的派生類物件不可以訪問基類的保護成員
prot.m_protect =1;
// 錯誤,保護繼承的派生類物件不可以訪問基類的私有成員
prot.m_private =
1;
// 定義乙個私有繼承的派生類物件
derived_protect priv;
// 錯誤,私有繼承的派生類物件不可以訪問基類的公有成員
priv.m_public =1;
// 錯誤,私有繼承的派生類物件不可以訪問基類的保護成員
priv.m_protect =1;
// 錯誤,私有繼承的派生類物件不可以訪問基類的私有成員
priv.m_private =
1;
現在,我們應該可以分清派生訪問說明符的作用了吧!公有繼承過來的基類成員對於派生類物件訪問限制不變,在基類裡是公有的、保護的、私有的在派生類裡還是保持公有、保護、私有。所以公有繼承的派生類物件可以訪問基類的公有成員但卻不能訪問基類的保護和私有成員。保護繼承過來的基類所有成員對於派生類物件來說訪問許可權變成了保護,而物件是不能訪問類的保護成員的,所以保護繼承的派生類物件不能訪問基類的任何成員。同樣的道理,私有繼承過來的基類成員對於派生類物件來說訪問許可權是私有,所以其對應的物件不能訪問基類的任何成員。
虛繼承
在多重繼承體系下(派生類繼承多個基類),往往會出現基類中又有更高階基類的情況,考慮下面這種繼承情況:
class
file
;class
inputfile
:public
file
;class
outputfile
:public
file
;class
iofile
:public
inputfile
,public
outputfile
;
將其轉換為繼承模型圖為:
這種情況下派生類iofile和基類file之間的相通路線有一條以上,這就是所謂的鑽石型或稜形繼承,最要命的是,iofile類通過 iofile -> inputfile -> file 這條繼承路線已經繼承了乙份filename成員變數,而通過 iofile -> outputfile -> file 這條繼承路線又繼承了乙份filename成員變數,也就是說成員變數filename執行了兩次複製。
解決以上問題的關鍵是使用虛繼承,令帶有此資料(filename)的類(file)成為虛基類(virtual base class)。所以將繼承體系改寫成如下:
當然,使用了虛繼承需要付出代價,比如:虛繼承的類物件會變大,虛基類的成員訪問速度也會變慢,同時虛基類的初始化會比較複雜,它必須由最底層的派生類負責初始化,規則如下:
1、位於繼承鏈最末端的子類的建構函式負責構造虛基類子物件。
2、虛基類的所有子類(無論直接的還是間接的)都必須在其建構函式中顯式指明該虛基類子物件的構造方式,否則編譯器將選擇以預設方式構造該子物件。
3、虛基類的所有子類(無論直接的還是間接的)都必須在其拷貝建構函式中顯式指明以拷貝方式構造該虛基類子物件,否則編譯器將選擇以預設方式構造該子物件。
ps:建議平時使用的時候能不用虛繼承就不要用,如果必須用的話盡量不要在虛基類中存放資料。
C 之類繼承
主要探索 1 派生類對基類protecteed public private三種資料訪問 和這三種繼承方式比較。2 派生類包含子物件。3 子類包含建構函式。通過public方式繼承 具體示例 include include using namespace std 定義基類 class people ...
C 之《類繼承》
c 中的類繼承按成員函式的繼承方式可以分為兩類 函式介面 宣告 繼承 function inte ce inheritance 和函式實現繼承 function implementation inheritance 而對於進行程式設計的程式設計師而言,其所想要的繼承方式大概可以分為以下三種 1 de...
C 基礎知識之類繼承
using system using system.collections.generic using system.linq using system.text namespace classinherit set pubic修飾,它的子類繼承得到 public void shout class ...