Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/163.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 调用隐式删除的复制构造函数_C++_Std_Copy Constructor_Factory Pattern_Move Constructor - Fatal编程技术网

C++ 调用隐式删除的复制构造函数

C++ 调用隐式删除的复制构造函数,c++,std,copy-constructor,factory-pattern,move-constructor,C++,Std,Copy Constructor,Factory Pattern,Move Constructor,我有以下设置: class MyClass { public: static MyClass Clone(const MyClass& other) { return MyClass(other, 10); } static MyClass CreateNormal(int x, int y) { return MyClass(int x, int y); } // There are a few more factory functions.

我有以下设置:

class MyClass {
 public:
  static MyClass Clone(const MyClass& other) { 
    return MyClass(other, 10);
  }

  static MyClass CreateNormal(int x, int y) {
    return MyClass(int x, int y);
  }

  // There are a few more factory functions.

 private:
  // Constructor 1
  MyClass(int x, int y) : b_(x, y) {}

  // Constructor 2
  MyClass(const MyClass& other, int c) : b_(other.b_, c) {}

  // And a lot more constructors.


  // NotMyClass has its copy constructor deleted.
  NotMyClass b_;
}

int main() {
  MyClass A(1,2);

  MyClass B = MyClass::Clone(A); // ERROR
}
有没有一种方法可以绕过这个问题而不修改
NotMyClass
? 发生此错误是因为隐式删除了
MyClass
的复制构造函数。有没有办法用std::Move()来解决这个问题


我无法删除工厂函数,因为实际的类有许多构造函数,并且为了清晰和理解,需要工厂函数。

假设c++11标准可用,您可以延长工厂方法返回的右值引用的生存期,而不是构造新对象,如下所示:

MyClass   A(1, 2);
MyClass&& B = MyClass::Clone(A);
增编: 正如patatahooligan在下面的评论中所指出的,在您的
MyClass::Clone
版本中可能存在复制构造函数调用。这可以/需要重写为

MyClass MyClass::Clone(const MyClass& other) {
    return {other, 10};
}
一旦C++17附带了强制拷贝省略,所有这些都将是完全不必要的,所以您可以期待


在C++03中,尽管解决方案较长且需要更多的代码,但仍有可能实现预期的结果。我提供两种选择:

与创建一组静态方法不同,我建议使用标记分派来表示不同的构造函数含义。这是通过使用具有明确名称但不包含数据的类型参数重载构造函数来实现的

struct clone_tag {};
class MyClass {
public:

    MyClass(int x, int y) : b_(x, y) {}
    MyClass(const MyClass& self, clone_tag) : b_(self.b_, 10) {}
private:

    NotMyClass b_;
};

int main() {
    MyClass   A(1, 2);
    MyClass   B(A, clone_tag());
}
或者,这甚至可以延伸到真正的工厂模式,即工厂的建筑和对象的最终建筑是分开的。这显然需要更多的时间来设置,但可能会提高代码质量,具体取决于不同构造函数路径的实际数量

class MyClass {
public:
    struct Clone {
        Clone(const MyClass& self) : self(self) {}
        const MyClass& self;
    };
    struct Init {
        Init(int x, int y) : x(x), y(y) {}
        int x, y;
    };

    MyClass(Init i) : b_(i.x, i.y) {}
    MyClass(Clone c) : b_(c.self.b_ , 10) {}
private:
    MyClass(const MyClass& other, int c) : b_(other.b_, c) {}

    NotMyClass b_;
};


int main() {
    MyClass   A = MyClass::Init(1, 2);
    MyClass   B = MyClass::Clone(A);
}


经过再三考虑,我意识到给出三种不同的选择可能会比一个不那么精确的简短回答更容易引起混乱。因此,我尝试按所需重构工作的顺序列出它们,尽管这只是对真实代码库的猜测。

假设c++11标准可用,您可以延长factory方法返回的右值引用的生存期,而不是构建新对象,如下所示:

MyClass   A(1, 2);
MyClass&& B = MyClass::Clone(A);
增编: 正如patatahooligan在下面的评论中所指出的,在您的
MyClass::Clone
版本中可能存在复制构造函数调用。这可以/需要重写为

MyClass MyClass::Clone(const MyClass& other) {
    return {other, 10};
}
一旦C++17附带了强制拷贝省略,所有这些都将是完全不必要的,所以您可以期待


在C++03中,尽管解决方案较长且需要更多的代码,但仍有可能实现预期的结果。我提供两种选择:

与创建一组静态方法不同,我建议使用标记分派来表示不同的构造函数含义。这是通过使用具有明确名称但不包含数据的类型参数重载构造函数来实现的

struct clone_tag {};
class MyClass {
public:

    MyClass(int x, int y) : b_(x, y) {}
    MyClass(const MyClass& self, clone_tag) : b_(self.b_, 10) {}
private:

    NotMyClass b_;
};

int main() {
    MyClass   A(1, 2);
    MyClass   B(A, clone_tag());
}
或者,这甚至可以延伸到真正的工厂模式,即工厂的建筑和对象的最终建筑是分开的。这显然需要更多的时间来设置,但可能会提高代码质量,具体取决于不同构造函数路径的实际数量

class MyClass {
public:
    struct Clone {
        Clone(const MyClass& self) : self(self) {}
        const MyClass& self;
    };
    struct Init {
        Init(int x, int y) : x(x), y(y) {}
        int x, y;
    };

    MyClass(Init i) : b_(i.x, i.y) {}
    MyClass(Clone c) : b_(c.self.b_ , 10) {}
private:
    MyClass(const MyClass& other, int c) : b_(other.b_, c) {}

    NotMyClass b_;
};


int main() {
    MyClass   A = MyClass::Init(1, 2);
    MyClass   B = MyClass::Clone(A);
}


经过再三考虑,我意识到给出三种不同的选择可能会比一个不那么精确的简短回答更容易引起混乱。因此我试图按需要重构的顺序列出它们,尽管这只是猜测你的真实代码基础。< /P>你有哪些C++标准?NotMyClass有一个移动构造函数吗?如果你想克隆一个不可复制的对象,那么你最好希望<代码> NotMyClass < /C> >自己有一个<代码>克隆()/<代码>方法。否则你会试图打破它的设计。你确定要复制这个不可复制的东西吗?您不想保留对它的引用吗?如果
NotMyClass
不提供复制构造函数,几乎肯定有原因。我假设它是库的一部分,所以请阅读其中的文档,了解为什么不能复制它,以及您有哪些替代方案。如果它是不应该复制的,那么您可能只需要创建一个,然后创建一个
NotMyClass*
NotMyClass&
。否则,它们可能会提供工厂函数,您可以在副本构造函数的初始值设定项列表中调用工厂函数。是。NotMyClass没有复制构造函数。但它确实提供了一个重复的功能。能够为使用复制函数的MyClass创建自己的CopyConstructor。谢谢哪个C++标准对你有用?NotMyClass有一个移动构造函数吗?如果你想克隆一个不可复制的对象,那么你最好希望<代码> NotMyClass < /C> >它自己有一个<代码>克隆()/<代码>方法。否则你会试图打破它的设计。你确定要复制这个不可复制的东西吗?您不想保留对它的引用吗?如果
NotMyClass
不提供复制构造函数,几乎肯定有原因。我假设它是库的一部分,所以请阅读其中的文档,了解为什么不能复制它,以及您有哪些替代方案。如果它是不应该复制的,那么您可能只需要创建一个,然后创建一个
NotMyClass*
NotMyClass&
。否则,它们可能会提供工厂函数,您可以在副本构造函数的初始值设定项列表中调用工厂函数。是。NotMyClass没有复制构造函数。但它确实提供了一个重复的功能。能够为使用复制函数的MyClass创建自己的CopyConstructor。谢谢想法不错,但我相信在clone的return语句中不能构造临时对象本身,因为它调用了MyClass的私有复制构造函数,而MyClass的私有复制构造函数将无法复制
MyClass::b_u
,因为它是一个不可复制的
NotMyClass
@patatahooligan你指的是我的代码吗?因为我假设OP的所有代码都是编译的,除了特别提到的地方。糟糕的是,我误读了代码,认为
b_u
是复制的,但它是