101

我了解到我永远无法访问私有变量,只能使用类中的 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;
4

6 回答 6

121

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

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

为什么:

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

如果您从作用域的角度来考虑它,这在语义上也是一种逻辑:“在修改私有变量时,我需要记住多少部分代码?” – 您需要牢记整个类的代码,这与运行时中存在哪些对象是正交的。

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

于 2010-11-07T08:34:15.340 回答
40

恕我直言,现有的答案在解释这个“为什么”方面做得很差——过于关注重申什么行为是有效的。“访问修饰符在类级别上起作用,而不是在对象级别上。” - 是的,但是为什么?

这里的总体概念是,设计、编写和维护一个类的程序员应该理解所需的 OO 封装并有权协调其实现。因此,如果您正在编写class X,您不仅要编码X x可以访问单个对象的代码如何使用它,还要编码如何:

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

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

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

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

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

于 2010-11-07T08:34:56.900 回答
11

为了理解答案,我想提醒你几个概念。

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

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

希望这能回答你的问题。

于 2012-05-23T13:14:12.997 回答
6

复制构造函数是类的成员函数,因此可以访问类的数据成员,即使是那些声明为“私有”的成员。

于 2010-11-07T09:44:49.470 回答
0

为什么制作该编译器的人允许这种行为,我们可以在复制构造函数或类中的任何方法中看到对象的隐藏成员(其类型与访问隐藏成员的类相同) 。

答案:因为当你在类中时,这意味着你是类的构建者或设计者也意味着你知道该类中的所有数据成员和方法,这就是他允许这种行为的原因,因为你构建了这个类,你知道每个关于它的事情不像课堂的用户,他们不像你一样了解课堂的每一件事。

隐藏有助于此类用户的数据成员或方法的想法,而不会将它们与不重要的事物混淆。

就是这样。

于 2021-11-28T01:14:09.133 回答