这可能是一个明显答案或重复的问题。如果是,抱歉,我会删除它。
为什么链接复制构造函数(如默认ctors或dtors),以便在调用派生类的复制构造函数之前调用基类的复制构造函数?对于复制构造函数和析构函数,它们分别在从base-to-derived和derived-to-base的链中被调用。为什么复制构造函数不是这种情况?例如,此代码:
class Base {
public:
Base() : basedata(rand()) { }
Base(const Base& src) : basedata(src.basedata) {
cout << "Base::Base(const Base&)" << endl;
}
void printdata() {
cout << basedata << endl;
}
private:
int basedata;
};
class Derived : public Base {
public:
Derived() { }
Derived(const Derived& d) {
cout << "Derived::Derived(const Derived&)" << endl;
}
};
srand(time(0));
Derived d1; // basedata is initialised to rand() thanks to Base::Base()
d1.printdata(); // prints the random number
Derived d2 = d1; // basedata is initialised to rand() again from Base::Base()
// Derived::Derived(const Derived&) is called but not
// Base::Base(const Base&)
d2.printdata(); // prints a different random number
复制构造函数不能(不能)真正复制对象,因为Derived::Derived(const Derived&)
无法访问basedata
来更改它。
我是否缺少一些关于复制构造函数的基本内容,以至于我的心智模型不正确,或者这个设计是否存在一些神秘(或非神秘)的原因?
答案 0 :(得分:21)
复制构造函数不能(不能)真正复制对象,因为
Derived::Derived(const Derived&)
无法访问pdata
来更改它。
当然可以:
Derived(const Derived& d)
: Base(d)
{
cout << "Derived::Derived(const B&)" << endl;
}
如果未在初始值设定项列表中指定基类构造函数,则会调用其默认构造函数。如果要调用默认构造函数以外的构造函数,则必须指定要调用的构造函数(以及使用哪些参数)。
至于为什么这种情况:为什么复制构造函数与任何其他构造函数有什么不同?作为实际问题的一个例子:
struct Base
{
Base() { }
Base(Base volatile&) { } // (1)
Base(Base const&) { } // (2)
};
struct Derived : Base
{
Derived(Derived&) { }
};
您希望Base
复制构造函数调用中的哪个Derived
复制构造函数?
答案 1 :(得分:3)
你可以:
Derived(const Derived& d) : Base(d) {
cout << "Derived::Derived(const B&)" << endl;
}
这会调用Base
Base
子对象上的d
副本构造函数。
“为什么”我不知道的答案。但通常没有答案。委员会只需选择一种方案或另一种方案。这似乎与语言的其他部分更加一致,例如Derived(int x)
不会自动调用Base(x)
。
答案 2 :(得分:2)
那是因为每个构造函数默认调用默认的基础构造函数:
Derived(const Derived& d) {
cout << "Derived::Derived(const B&)" << endl;
}
将致电Base()
。
这是由标准定义的。我喜欢这样,而不是在类上调用复制构造函数。你当然可以明确地称之为。