为什么我可以在复制构造函数中访问私有变量?

dem*_*ing 78 c++ private access-specifier

我了解到我永远不能访问私有变量,只能使用类中的get函数.但是为什么我可以在复制构造函数中访问它?

例:

Field::Field(const Field& f)
{
  pFirst = new T[f.capacity()];

  pLast = pFirst + (f.pLast - f.pFirst);
  pEnd  = pFirst + (f.pEnd - f.pFirst);
  std::copy(f.pFirst, f.pLast, pFirst);
}
Run Code Online (Sandbox Code Playgroud)

我的声明:

private:
  T *pFirst,*pLast,*pEnd;
Run Code Online (Sandbox Code Playgroud)

aio*_*obe 105

访问修饰符在类级别上工作,而不在对象级别上工作.

也就是说,同一类的两个对象可以访问彼此的私有数据.

为什么:

主要是由于效率.如果访问修饰符在对象级别上工作,则this == other每次访问时都要检查是否存在不可忽略的运行时开销other.x.

如果从角度范围的角度来考虑它,它在语义上也是合乎逻辑的:"在修改私有变量时,我需要记住大部分代码吗?" - 您需要记住整个类的代码,这与运行时中存在的对象是正交的.

在编写复制构造函数和赋值运算符时,它非常方便.


Ale*_*rty 34

您可以从类中访问类的私有成员,甚至是其他实例的私有成员.


Ton*_*roy 30

恕我直言,现有的答案很难解释这个"为什么" - 过分关注重复什么行为是有效的."访问修饰符在类级别上工作,而不是在对象级别上工作." - 是的,但是为什么?

这里的首要概念是,程序员正在设计,编写和维护一个类,这个类被期望理解所需的OO封装并有权协调其实现.因此,如果您正在编写class X,那么您不仅要编码X x具有访问权限的代码如何使用单个对象,还要编写如何:

  • 派生类能够与它交互(通过可选的纯虚函数和/或受保护的访问),以及
  • 不同的X对象合作提供预期的行为,同时尊重您的设计中的后置条件和不变量.

它不仅仅是复制构造函数 - 很多操作都可能涉及到类的两个或更多实例:如果你要进行比较,添加/乘法/除法,复制构造,克隆,分配等等,那么通常就是你的情况或者只是必须访问另一个对象中的私有和/或受保护数据,或者希望它允许更简单,更快速或通常更好的函数实现.

具体来说,这些操作可能希望利用特权访问来执行以下操作:

  • (复制构造函数)在初始化列表中使用"rhs"(右侧)对象的私有成员,以便成员变量本身是复制构造的,而不是默认构造的(如果合法的话),然后也分配(再次,如果合法)
  • 共享资源 - 文件句柄,共享内存段,shared_ptrs引用数据等.
  • 取得对事物的所有权,例如auto_ptr<>将所有权"移动"到正在建造的对象
  • 复制私有"缓存",校准或状态成员,以最佳可用状态构造新对象,而无需从头开始重新生成它们
  • 复制/访问正在复制的对象中保存的诊断/跟踪信息,这些信息不能通过公共API访问,但可能被某些后来的异常对象或日志记录使用(例如,有关"原始"非复制构造实例的时间/环境的信息)被建造了)
  • 执行一些数据的更有效的副本:例如,对象可能具有例如unordered_map成员但公开只暴露begin()end()迭代器 - 直接访问size()您可以reserve更快地复制; 更糟的是,如果他们只会暴露at()insert()否则throw....
  • 将引用复制回父级/协调/管理对象,这些对象可能是未知的或只写为客户端代码

  • 我认为最大的"原因"是,如果访问修饰符在对象级别上工作,每次访问`other.x`时,检查是否`this == other`将是一个巨大的运行时开销. (2认同)
  • @aioobe 我认为你的答案应该更加突出。虽然托尼的回答非常好且概念化,但如果我是一个赌徒,我敢打赌您的回答是做出选择的实际历史原因。它不仅性能更高,而且更简单。对于 Bjarne 来说,这将是一个很好的问题! (2认同)

小智 11

为了理解答案,我想提醒你一些概念.

  1. 无论您创建多少个对象,该类的内存中只有一个函数的副本.这意味着只创建一次函数.但是,对于类的每个实例,变量都是独立的.
  2. this 调用时,指针被传递给每个函数.

现在是因为this指针,函数能够定位该特定实例的变量.无论是公共私人.它可以在该函数内访问.现在,如果我们将指针传递给同一个类的另一个对象.使用这个第二个指针,我们将能够访问私人成员.

希望这能回答你的问题.


Boj*_*zec 6

复制构造函数是类的成员函数,因此可以访问类的数据成员,甚至是那些声明为'private'的成员.

  • 作为懂语言的人,我明白你的意思.但是,如果我不懂语言,我会认为你只是向我重复这个问题. (3认同)