In C++ , access control works on per-class basis
, not on per-object basis
.
重要的东西要说三遍,所以…
1.在 C++
中,存取控制能力是类的性质,不是对象的性质。
2.在 C++
中,存取控制能力是类的性质,不是对象的性质。
3.在 C++
中,存取控制能力是类的性质,不是对象的性质。
作为在阅读<<Inside the object model>>
一书的时候,里面有写地方看的比较混乱,就查阅了<<C++ Primer>>
中的相关章节,看到了类中成员存取控制那一章节,突然想到了一个困惑自己多年的问题。于是乎上网搜答案,答案支离破碎,而且有点不知所云。在知乎上看见一个大牛说了一句:
存取能力是类的性质,不是对象的性质。
乍看之下我没读懂,然后我一直反复思索这句话的意思,但是苦于没有例子,实在是难以悟出点东西。后来翻墙去Stack Overflow
搜了下答案,有人提出来同样的问题,就研究了下,终于对这句话有点理解,怕自己忘记了,所以写下博文。
首先确立一个基本观点,然后用例子加以解释。
在public
继承下,Base class 的公有成员成为了Derived class 的公有成员,同理可以类比保护成员。
那么我看一个例子:
#include<iostream>
#include <iostream>
class Trival{
protected:
int val;
public:
Trival(const Trival& another){
val = another.val;//!!!
}
};
为何我们的object another
可以存取私有成员呢?其实我很早就对此感到疑惑,但是但是水平欠缺,提问都不会,而且当时碍于书上的规则就是这么写的。
按照书上的规则,val
是保护数据成员,我们的another成员是不能对其进行直接存取的,但是我们定义拷贝构造函数的时候确是习以为常的。
这个地方是我自己理解出现了偏差。我认为存取能力的是对象的性质。也就是说某数据成员是私有的,那么我们的对象就不能直接存取它。但是如此理解是存在问题的,我们无法解释在类内部对私有或者受保护成员的存取操作。所以我会在开头说,存取控制是类的性质,不是对象的性质。现在我们就可以理解了。既然是类的性质,那么类就是用来区分是否可以访问的依据。只要是在类的内部,我们就可以访问它,而不是说对象就不能直接访问私有成员。
经过上面的解释大家应该有些感性的认识。
下面抛出一个问题,仍然同存取控制有关。
#include <iostream>
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<iostream>
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;
}