【问题标题】:"member of type foo has private copy constructor" error: why's it an error?“类型 foo 的成员具有私有复制构造函数”错误:为什么会出错?
【发布时间】:2012-05-18 16:07:23
【问题描述】:

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

#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; }

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

【问题讨论】:

  • 出现错误的代码行是什么?
  • 不出所料,这是foo字段的声明;-)
  • 因为你的类 my_class 有一个隐式的编译器生成的复制构造函数,它只复制所有字段。如果someone_elses 具有私有复制构造函数,则无法复制foo 字段。您应该为 my_class 编写自己的复制构造函数,以实现正确的复制。
  • 我猜你在某个地方试图复制这样的对象。就像按值传递给函数一样。
  • Aside:“我知道我可以解决这个问题”——不是真的。不要忘记Rule of Three

标签: c++ class copy-constructor


【解决方案1】:

在第一个版本中,当您复制 my_class 的实例时,并且您必须在没有向我们展示的地方,您正在对 someone_elses 进行深层复制。

在后一个版本中,当您执行相同操作时,您正在制作指向someone_elses 实例的指针的浅拷贝。因此,您无需制作副本,而是在my_class 的两个副本中都有指向同一实例的指针。

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

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

【讨论】:

  • +1 请注意,OP 必须在未公开的代码部分中制作一些副本。如果没有复制,则无法生成复制构造函数不是问题。
  • 谢谢。我不知道我 am 在任何地方复制 my_class - 但我不小心写了一个 Java 式初始化程序 my_class bar = my_class();,它试图使用复制构造函数。 掌心
【解决方案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();
  //...
};

【讨论】:

    【解决方案3】:

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

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

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

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

    【讨论】:

      【解决方案4】:

      因为my_class的拷贝构造函数会调用foo的拷贝构造函数。这是一个对象,不是指针,所以需要调用它的拷贝构造函数。

      【讨论】:

        【解决方案5】:

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

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

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

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-03-27
          • 1970-01-01
          • 2018-11-09
          • 1970-01-01
          • 2019-03-15
          • 1970-01-01
          相关资源
          最近更新 更多