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

时间:2010-11-07 08:30:28

标签: 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);
}

我的声明:

private:
  T *pFirst,*pLast,*pEnd;

5 个答案:

答案 0 :(得分:101)

访问修饰符适用于类级别,而不适用于对象级别

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

为什么:

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

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

编写复制构造函数和赋值运算符时非常方便。

答案 1 :(得分:32)

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

答案 2 :(得分:27)

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

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

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

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

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

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

答案 3 :(得分:11)

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

  1. 无论您创建多少个对象,该类的内存中只有一个函数的副本。这意味着只创建一次函数。但是,对于每个类的实例,变量都是独立的。
  2. this指针在被调用时传递给每个函数。
  3. 现在由于this指针,函数能够找到该特定实例的变量。无论是公共私人。它可以在该函数内访问。现在,如果我们将指针传递给同一个类的另一个对象。使用这个第二个指针,我们将能够访问私人成员。

    希望这能回答你的问题。

答案 4 :(得分:6)

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