为什么同一类的对象可以访问彼此的私有数据?

Kei*_*ith 91 c++ private-members

为什么同一类的对象可以访问彼此的私有数据?

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;
}
Run Code Online (Sandbox Code Playgroud)

这个代码有效.对象a完全可以从对象b访问私有数据并将其返回.为什么会这样?我认为私人数据是私人的.(我开始试图理解pimpl习语中的复制构造函数,但后来我发现我甚至不理解这种简单的情况.)

AnT*_*AnT 74

因为这就是它在C++中的工作方式.在C++中,访问控制基于每个类而不是基于每个对象.

C++中的访问控制是作为静态编译时功能实现的.我认为很明显,在编译时实际上不可能实现任何有意义的每对象访问控制.只有每类控制才能实现.

受保护的访问规范中存在一些每对象控制的提示,这就是为什么它甚至在标准中有自己的专用章节(11.5).但是,那里描述的任何每个对象的特征仍然相当简陋.同样,C++中的访问控制意味着在每个类的基础上工作.

  • +1.C++在编译时机制上很重要,在运行时机制上并没有那么大.相当不错的一般规则. (7认同)
  • 您的"在编译时实际上无法实现任何有意义的每对象访问控制".为什么不?在`void X :: f(X&x)`中,编译器很容易区分`this-> a`和`xa`.如果调用`xf(x)`,编译器不可能(总是)知道`*this`和`x`实际上是同一个对象,但是我很可能看到语言设计者发现它没问题. (4认同)

vse*_*har 28

"私人"并不是一种真正的访问控制机制,因为"我在facebook上制作了我的照片,因此你无法看到它们."

在C++中,"私有"只是说这些是你(类的编码器)在未来版本中可能会改变的类的一部分,等等,你不希望其他编码人员使用你的类来依赖它们的存在或功能.

如果您想要真正的访问控制,您应该实现真正的数据安全技术.


Jac*_*Zhu 12

这是一个很好的问题,我最近遇到过这个问题.我与同事们进行了一些讨论,这是我们讨论的总结:这是设计的.这并不意味着这种设计对于所有情况都是完全合理的,但必须考虑为什么选择每个类私有.我们可以想到的可能原因包括:

首先,每个实例访问控制的成本可能非常高.这个帖子中的其他人已经讨论过这个问题.理论上,这可以通过指针检查来完成.但是,这不能在编译时完成,并且只能在运行时完成.因此,您必须在运行时识别每个成员的访问控制,并且当它被违反时,可能只会引发异常.成本很高.

其次,每个类访问控制都有自己的用例,比如copy constructor或operator =.如果每个实例都有访问控制,那么很难实现它们.

此外,访问控制主要来自编程/语言角度,用于如何模块化/控制对代码/成员的访问,而不是数据.


And*_*ron 11

这有点像任意语言设计决定.例如,在Ruby中,private实际上意味着私有,因为"只有实例才能访问自己的私有数据成员".但是,这有点限制.

正如注释中所指出的,复制构造函数和赋值运算符是您直接访问其他实例的私有数据成员的常见位置.有不太明显的原因.

考虑以下情况.您正在实施OO链接列表.链表有一个用于管理指针的嵌套节点类.您可以实现此节点类,以便它自己管理指针(而不是将指针公开并由列表管理).在这种情况下,您希望节点对象想要在典型的复制构造函数和赋值运算符的其他位置修改其他节点对象的指针.


Ada*_*ras 6

诀窍是记住数据是private类的,而不是实例。类中的任何方法都可以访问该类的任何实例的私有数据;除非您禁止显式访问其他实例的私有数据成员的方法,否则无法将数据保持在实例内私有。


Yee*_*Fei -9

私有数据将一直保持私有状态,直到有权访问该数据的人将其透露给其他人为止。

这个概念也适用于其他情况,例如:

class cMyClass
{
public:
   // ...
   // omitted for clarity
   // ...

   void Withdraw(int iAmount)
   {
      iTheSecretVault -= iAmount;
   }

private:
   int iTheSecretVault;
};
Run Code Online (Sandbox Code Playgroud)

怎么会有人把钱取出来呢?:)

  • 此示例不涉及一个类实例访问另一实例的私有数据成员。 (3认同)