我试图定义一个这样的类:
#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; }
我的问题是为什么编译器会关心对象的字段是否实现了可访问的拷贝构造函数?
答案 0 :(得分:3)
在第一个版本中,当您复制my_class
的实例,并且您必须在某个您未向我们展示的位置时,您正在对someone_elses
进行深层复制。
在后一版本中,当你做同样的事情时,你正在制作一个指向someone_elses
实例的指针的浅表副本。因此,您不会复制,而是在my_class
的两个副本中都指向同一个实例。
因为你实际上在析构函数中删除了someone_elses
,所以你会遇到各种各样的问题。你需要能够复制someone_elses
,但似乎你不允许因为某种原因而认为那个班级的作者认为它是如此重要以致它们无法实现。
如何回应此问题在很大程度上取决于您遗漏的细节。可能是您不能允许my_class
的副本,并且应该使其复制构造函数也是私有的。这当然会在其他地方破坏某些东西,因为如果没有使用它就不会创建构造函数。
答案 1 :(得分: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();
//...
};
答案 2 :(得分:2)
C ++ 03 standard 12.8(复制类对象)复制构造:
以适合其类型的方式复制每个子对象:
- 如果子对象是类类型,则使用该类的复制构造函数;
- 如果子对象是一个数组,则以适合于元素类型的方式复制每个元素;
- 如果子对象是标量类型,则使用内置赋值运算符。
如果您的案例中的子对象someone_elses
的复制构造函数为private
,则您的代码会破坏第一个要求,因此无法使用它,因此编译器会准确地指出错误。
答案 3 :(得分:1)
因为my_class
的复制构造函数将调用foo
的复制构造函数。这是一个对象,而不是一个指针,因此需要调用它的复制构造函数。
答案 4 :(得分: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
。因此错误。