In C++ , access control works on per-class basis
, not on per-object basis
.
重要的東西要說三遍,所以…
1.在 C++
中,存取控制能力是類的性質,不是對象的性質。
2.在 C++
中,存取控制能力是類的性質,不是對象的性質。
3.在 C++
中,存取控制能力是類的性質,不是對象的性質。
作為在閱讀<
一書的時候,裡面有寫地方看的比較混亂,就查閱了<
中的相關章節,看到了類中成員存取控制那一章節,突然想到了一個困惑自己多年的問題。於是乎上網搜答案,答案支離破碎,而且有點不知所雲。在知乎上看見一個大牛說了一句:
存取能力是類的性質,不是對象的性質。
乍看之下我沒讀懂,然後我一直反復思索這句話的意思,但是苦於沒有例子,實在是難以悟出點東西。後來翻牆去Stack Overflow
搜了下答案,有人提出來同樣的問題,就研究了下,終於對這句話有點理解,怕自己忘記了,所以寫下博文。
首先確立一個基本觀點,然後用例子加以解釋。
在public
繼承下,Base class 的公有成員成為了Derived class 的公有成員,同理可以類比其余兩種成員。
那麼我看一個例子:
#include
#include
class Trival{
private:
int val;
public:
Trival(const Trival& another){
val = another.val;//!!!
}
};
為何我們的object another
可以存取私有成員呢?其實我很早就對此感到疑惑,但是但是水平欠缺,提問都不會,而且當時礙於書上的規則就是這麼寫的。
按照書上的規則,val
是私有數據成員,我們的another成員是不能對其進行直接存取的,但是我們定義拷貝構造函數的時候確是習以為常的。
這個地方是我自己理解出現了偏差。我認為存取能力的是對象的性質。也就是說某數據成員是私有的,那麼我們的對象就不能直接存取它。但是如此理解是存在問題的,我們無法解釋在類內部對私有或者受保護成員的存取操作。所以我會在開頭說,存取控制是類的性質,不是對象的性質。現在我們就可以理解了。既然是類的性質,那麼類就是用來區分是否可以訪問的依據。只要是在類的內部,我們就可以訪問它,而不是說對象就不能直接訪問私有成員。
經過上面的解釋大家應該有些感性的認識。
下面拋出一個問題,仍然同存取控制有關。
#include
class Trival{
protected:
int val;
};
class Derived :public Trival{
public:
void func(Trival* t1,Derived* d1){
//t1->val;報錯。
d1->val;
val;
}
};
可以想一下為何會報錯,如果可以理解開頭的那句話應該就沒問題了。
為何底下的那兩個是正確的呢?
我想不用過多的解釋了。簡單的說一句。對於上面的t1
來說,我們不可以直接訪問自己的私有成員val
,因為我們已經不是在Trival
類中了,所以直接進行訪問就是不合法的。但是這種形式常常會誤導我們,讓我們以為成員的存取訪問是對象的性質。
綜上所述,我們的區分依據應該是類內類外。也就是說存取能力是類的屬性。
如果我將的不能讓你明白,請參考原文或者與我探討,我現在的理解可能依然是欠缺的。
下面附上Stakc Overflow
的鏈接
戳我進去
考慮到牆太厚,做次搬運工。
In Public Inheritance:
All Public members of the Base Class become Public Members of the derived class &
All Protected members of the Base Class become Protected Members of the Derived Class.
As per the above rule:
protected member x from A becomes protected member of class B.
class B can access its own protected members in its member function foo but it can only access members of A through which it was derived not all A classes.
In this case, class B contains a A pointer a, It cannot access the protected members of this contained class.
Why can the B::foo() access the members of the contained class B pointer b?
The rule is:
In C++ access control works on per-class basis, not on per-object basis.
So an instance of class B will always have access to all the members of another instance of class B.
Below is a example :
#include
class MyClass
{
public:
MyClass (const std::string& data) : mData(data)
{
}
const std::string& getData(const MyClass &instance) const
{
return instance.mData;
}
private:
std::string mData;
};
int main() {
MyClass a("Stack");
MyClass b("Overflow");
std::cout << "b via a = " << a.getData(b) << std::endl;
return 0;
}