4

我试图定义一个这样的类:

#include <library/foo.h>

class my_class {
private:
  someone_elses foo;
public:
  myclass();
  ~myclass();
  //...
};

但是编译器失败了:“someone_elses 类型的字段 foo 有一个私有复制构造函数”。现在我知道我可以通过以下方式解决这个问题:

class my_class {
private:
  someone_elses *foo;
//...
};

my_class::my_class() { foo = new someone_elses(); }
my_class::~my_class() { delete foo; }

我的问题是为什么编译器关心对象的字段是否实现了可访问的复制构造函数?

4

5 回答 5

3

在第一个版本中,当您my_class复制someone_elses.

在后一个版本中,当您做同样的事情时,您正在制作指向someone_elses. 因此,您无需制作副本,而是在my_class.

由于您实际上是someone_elses在析构函数中删除,因此您将遇到各种问题。您需要能够复制someone_elses,但似乎由于某种原因不允许您复制,因为该课程的作者认为如此重要以至于无法复制。

如何应对这个问题在很大程度上取决于你遗漏的细节。可能是您不能允许复制my_class并且也应该将其复制构造函数设为私有。这当然会在其他地方破坏某些东西,因为如果不使用该构造函数,则不会创建它。

于 2012-05-18T16:16:25.207 回答
2

原因是您的my_class复制构造函数调用了someone_elses' 复制构造函数。您必须定义一个不复制构造的复制构造函数someone_elses,尽管从语义上讲这没有多大意义。

class my_class {
private:
  someone_elses foo;
public:
  my_class(const my_class& rhs) {
   // do nothing, end up with default constructed someone_elses.
  } 
  myclass();
  ~myclass();
  //...
};
于 2012-05-18T16:13:02.847 回答
2

C++03标准12.8(复制类对象)复制构造:

每个子对象都以适合其类型的方式复制:

  • 如果子对象是类类型,则使用该类的复制构造函数;
  • 如果子对象是一个数组,则以适合元素类型的方式复制每个元素;
  • 如果子对象是标量类型,则使用内置赋值运算符。

someone_elses您的代码违反了第一个要求,如果您的情况下的子对象的复制构造函数private不能使用,因此编译器会准确指出错误。

于 2012-05-18T16:14:45.163 回答
1

因为 的复制构造函数my_class会调用 的复制构造函数foo。这是一个对象,而不是指针,因此需要调用它的复制构造函数。

于 2012-05-18T16:11:20.070 回答
1

为什么编译器关心对象的字段是否实现了可访问的复制构造函数?

因为您的程序在my_class的隐式复制构造函数中调用它。考虑:

int main () {
  my_class m1;
  my_class m2(m1);
}

m2调用的创建my_class::my_class(const my_class&)。如果您没有提供,系统会自动为您提供一个。此隐式复制构造函数仅将 的每个字段复制m1到 的相应字段中m2。具体来说,它必须复制foo.

但是,由于someone_elses::someone_else(const someone_else&)是私有的,它不能复制foo. 因此错误。

于 2012-05-18T16:14:08.157 回答