为什么同一类的对象可以访问对方的私有数据?
为什么同一类的对象可以访问对方的私有数据?
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习语中的拷贝构造函数,但是后来我发现我甚至不理解这个简单的情况。)
因为这就是它在C ++中的工作原理。 在C ++中,访问控制在每个类的基础上工作,而不是在每个对象的基础上工作。
C ++中的访问控制是作为静态编译时function实现的。 我认为很明显,在编译时实现任何有意义的每对象访问控制是不太可能的。 只有按class级的控制可以这样实施。
每个对象控件的一些提示存在于受保护的访问规范中,这就是为什么它甚至在标准(11.5)中有自己的专用章节的原因。 但是,这里所描述的每个对象特征还是相当简单的。 同样,C ++中的访问控制意味着在每个类的基础上工作。
“私人”并不是真正的访问控制机制,因为“我把我的照片私人化,所以你看不到它们”。
在C ++中,“private”只是说这些是类(类的编码器)在将来的版本中可能会改变的类的一部分,而您不希望其他编码器使用您的类来依赖它们的存在或function。
如果你想要真正的访问控制,你应该实现真正的数据安全技术。
这是一个很好的问题,最近我也遇到过这个问题。 我和同事进行了一些讨论,下面是我们讨论的总结:这是devise。 这并不意味着这种devise对于所有情况都是完全合理的,但是为什么select每个class级的私人设施都必须考虑一些因素。 我们可以想到的可能的原因包括:
首先,每个实例访问控制的成本可能非常高。 这已经在这个线程中被别人讨论过了。 从理论上讲,这可以通过这个指针检查来完成。 但是,这不能在编译时完成,只能在运行时完成。 因此,您必须在运行时识别每个成员的访问控制,并且在违反时可能只会引发exception。 成本高。
其次,每个类的访问控制都有自己的用例,如复制构造函数或者operator =。 如果访问控制是每个实例,那么实现它们将是困难的。
另外,访问控制主要从编程/语言的angular度来看,如何模块化/控制对代码/成员的访问,而不是数据。
这是一个任意的语言devise决定。 例如,在Ruby中 , private
就是私有的,就像“只有实例可以访问它自己的私有数据成员”一样。 但是,这有些限制。
正如在注释中所指出的那样,复制构造函数和赋值运算符是直接访问另一个实例的私有数据成员的常见位置。 原因不太明显。
考虑以下情况。 你正在实现一个面向对象的链表。 链表具有用于pipe理指针的嵌套节点类。 你可以实现这个节点类,以便它pipe理指针本身(而不是指针公开并由列表pipe理)。 在这种情况下,节点对象需要在其他地方修改其他节点对象的指针,典型的复制构造函数和赋值操作符。
诀窍是记住数据对于类是private
的,而不是类的实例 。 你的类中的任何方法都可以访问该类的任何实例的私有数据; 除非禁止显式访问其他实例的私有数据成员的方法,否则没有办法将数据保留在实例中。
除了上面的所有答案之外,还可以考虑定制拷贝构造函数,赋值运算符以及为其他实例运行的类编写的所有其他函数。 您将需要所有这些数据成员的访问函数。
私人数据保持私人状态,直到有人访问私人数据才能将其泄露给其他人。
这个概念也适用于其他情况,比如:
class cMyClass { public: // ... // omitted for clarity // ... void Withdraw(int iAmount) { iTheSecretVault -= iAmount; } private: int iTheSecretVault; };
怎么能拿钱? 🙂