为什么同一个类的对象可以访问彼此的私有数据?
class TrivialClass {
public:
TrivialClass(const std::string& data) :
mData(data) {};
const std::string& getData(const TrivialClass& rhs) const {
return rhs.mData;
};
private:
std::string mData;
};
int main() {
TrivialClass a("fish");
TrivialClass b("heads");
std::cout << "b via a = " << a.getData(b) << std::endl;
return 0;
}
这段代码可以工作。对象a完全有可能从对象b访问私有数据并返回它。为什么会这样呢?我认为私有数据是私有的。(我一开始试图理解pimpl习惯用法中的复制构造函数,但后来我发现我甚至不理解这个简单的情况。)
7条答案
按热度按时间mkshixfv1#
因为这就是C的工作方式,在C中,访问控制是基于每个类的,而不是基于每个对象的。
C中的访问控制是作为一个静态的编译时特性来实现的。我认为很明显,在编译时实现任何有意义的每对象访问控制都是不可能的。只有每类访问控制才能以这种方式实现。
在 protected access 规范中有一些关于每对象控制的提示,这就是为什么它在标准(11.5)中有自己的专门章节。但是那里描述的每对象特性仍然是相当初级的。同样,C中的访问控制是以每类为基础的。
wfauudbj2#
“隐私”并不是真正意义上的“访问控制”机制,“我把我在Facebook上的照片设为隐私,这样你就看不到了。”
在C++中,“private”只是表示这些是类的一部分,您(类的编码者)可能会在将来的版本中进行更改,等等,并且您不希望其他使用您的类的编码者依赖于它们的存在或功能。
如果你想要真正的访问控制,你应该实现真正的数据安全技术。
6tr1vspr3#
这在某种程度上是一种任意的语言设计决策,例如,在Ruby中,
private
实际上意味着私有,就像“只有示例可以访问它自己的私有数据成员”一样。正如在注解中指出的,复制构造函数和赋值运算符是直接访问另一个示例的私有数据成员的常见地方,原因不太明显。
考虑下面的情况。你正在实现一个OO链表。链表有一个嵌套的节点类来管理指针。你可以实现这个节点类来管理指针本身(而不是使指针公开并由列表管理)。在这种情况下,你会有节点对象想要修改其他节点对象的指针在其他地方,典型的复制构造函数和赋值运算符。
xesrikrc4#
这是一个很好的问题,我最近也遇到过这个问题,我曾与同事讨论过,现将讨论的内容总结如下:这是一种设计。这并不意味着这种设计对所有情况都是完全合理的,但必须考虑为什么选择per class private。我们可以想到的可能原因包括:
首先,每个示例访问控制的成本可能非常高。这一点在本主题中已经讨论过。理论上,这可以通过 this 指针检查来完成。但是,这不能在编译时完成,只能在运行时完成。因此,您必须在运行时确定每个成员的访问控制。当它被违反时,可能只会引发异常,代价很高。
其次,类访问控制有其自身的用例,如复制构造函数或operator =,如果是示例访问控制,则很难实现。
另外,访问控制主要是从编程/语言的Angular ,针对如何模块化/控制对代码/成员的访问,而不是数据。
ckx4rj1h5#
诀窍是记住数据对于类是
private
,而不是类的示例,类中的任何方法都可以访问该类的任何示例的私有数据;除非你禁止显式访问其他示例的私有数据成员的方法,否则没有一种方法可以保持示例中的数据私有。6ojccjat6#
除了上面的所有答案之外,考虑定制的复制构造函数、赋值运算符和所有其他要为类编写的函数,这些函数对 * 其他示例 * 进行操作。您需要为所有这些数据成员编写访问器函数。
hgncfbus7#
私有数据在有权访问它的人将其泄露给其他人之前一直是私有的。
这一概念也适用于其他情况,例如:
怎么会有人把钱取出来呢?:)