C++類的訪問控制
前言
C++類中關於訪問說明符的關鍵字是public,protected和private,由於C++的繼承的訪問說明符不同,這裡會牽扯出非常多不同的情況,本文嘗試對此進行整理
無繼承
public,protected和private這三個訪問說明符其實是針對使用該類的程式碼而言的,如下
class Test {
public:
int a;
protected:
int b;
private:
int c;
}
其中a是可以又test例項化的物件訪問的,而b和c是不行的
Test t;
t.a; //合法
t.b; //非法
t.c; //非法
而對函式內部的方法而言,是可以訪問所有資料成員的(這裡不討論靜態與非靜態的區別)
class Test {
public:
int a;
//方法可以訪問所有資料成員
void f1() {
cout << a << endl;
}
void f2() {
cout << b << endl;
}
void f3() {
cout << c << endl;
}
protected:
int b;
private:
int c;
}
友元
一個類可以允許其他類或者函式訪問他的非公有成員,方法時令其他類或者函式成為它的友元,定義友元也很方便,只要增加一條以friend開頭的函式宣告即可
class Test {
//宣告函式f3為Test類的友元
friend void f3();
}
外部函式f3現在可以訪問Test類的非公有成員了
訪問控制與繼承
每個類都可以控制它的成員對於派生類的可訪問性
protected
protected說明符說明的是基類希望和派生類共享的成員,但是派生類及其友元只能訪問派生類物件中的基類部分的受保護成員,也就是說它能訪問的是繼承下來的那個成員,它還是不能訪問普通的基類物件中的受保護成員。這聽起來有點繞,看下面的例子:
class Base {
protected:
int a = 100;
}
class Son : public Base {
protected:
int a = 200;
public:
//合法,輸出200
void f1() {
cout << a << endl;
}
//合法,輸出100
void f2() {
cout << Base::d << endl;
}
//非法,不能訪問一般基類的受保護物件
void f3(Base& ba) {
cout << ba.d << endl;
}
}
公有,私有和受保護繼承
一個類對其繼承得到的成員的訪問許可權受兩個因素影響:一是基類中該成員的訪問說明符,二是派生列表中的訪問說明符
看下面的例子:
class Base {
protected:
int pro_mem = 100;
private:
int pri_mem = 20;
public:
int pub_mem = 10;
};
class Pub_Son : public Base{
public:
//合法,輸出10
void f1() {
cout << pub_mem << endl;
}
//合法,輸出100
void f2() {
cout << pro_mem << endl;
}
//非法,派生類不能訪問繼承來的私有成員
void f3() {
cout << pri_mem << endl;
}
};
class Pub_Son : private Base{
public:
//合法,輸出10
void f1() {
cout << pub_mem << endl;
}
//合法,輸出100
void f2() {
cout << pro_mem << endl;
}
//非法,派生類不能訪問繼承來的私有成員
void f3() {
cout << pri_mem << endl;
}
};
由例子可見,派生訪問說明符對於派生類的成員(及友元)能否訪問其直接基類的成員沒什麼影響,對基類的訪問許可權只與基類中的訪問說明符有關。
派生訪問說明符的目的是控制派生類使用者(也就是例項化的物件)對於基類成員的訪問許可權
看下面的例子
Pub_Son son1;
Pub_Son son2;
//合法
son1.pub_mem;
//非法
son2.pub_mem;
如果繼承是共有的,那麼成員將遵循其原有的訪問說明符,此時pub_mem在son1中也是public的,所以可以直接訪問。如果繼承是私有的,那麼在派生類中,父類的成員都是私有的,所以在son2中,pub_mem是私有的,所以無法直接訪問。同理如果是受保護繼承,那麼在派生類中,父類的所有成員都是受保護的
可以參見下表:
子類是繼承了父類的私有成員的,但是這對子類是隱藏的,所以表中寫了無。
此錶轉載自網路
總結一下就是記住幾個基本的訪問原則,然後記住三種繼承的不同就可以了,遇到更復雜的可以到時候查一下工具書,死記硬背也沒什麼意義