Vin*_*Pii 35 c++ language-design copy-constructor
考虑一个类层次结构,其中A
是基类并B
派生自A
.
如果未定义复制构造函数B
,编译器将合成一个.调用时,此复制构造函数将调用基类复制构造函数(即使是合成的构造函数,如果用户没有提供).
#include <iostream>
class A {
int a;
public:
A() {
std::cout << "A::Default constructor" << std::endl;
}
A(const A& rhs) {
std::cout << "A::Copy constructor" << std::endl;
}
};
class B : public A {
int b;
public:
B() {
std::cout << "B::Default constructor" << std::endl;
}
};
int main(int argc, const char *argv[])
{
std::cout << "Creating B" << std::endl;
B b1;
std::cout << "Creating B by copy" << std::endl;
B b2(b1);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出:
Creating B
A::Default constructor
B::Default constructor
Creating B by copy
A::Copy constructor
Run Code Online (Sandbox Code Playgroud)
如果用户定义了自己的复制构造函数B
,则在调用时,此复制构造函数将调用基类默认构造函数,除非明确存在对基类复制构造函数的调用(例如,在初始化列表中).
#include <iostream>
class A {
int a;
public:
A() {
std::cout << "A::Default constructor" << std::endl;
}
A(const A& rhs) {
std::cout << "A::Copy constructor" << std::endl;
}
};
class B : public A {
int b;
public:
B() {
std::cout << "B::Default constructor" << std::endl;
}
B(const B& rhs) {
std::cout << "B::Copy constructor" << std::endl;
}
};
int main(int argc, const char *argv[])
{
std::cout << "Creating B" << std::endl;
B b1;
std::cout << "Creating B by copy" << std::endl;
B b2(b1);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出:
Creating B
A::Default constructor
B::Default constructor
Creating B by copy
A::Default constructor
B::Copy constructor
Run Code Online (Sandbox Code Playgroud)
我的问题是,为什么用户定义的复制构造函数不会将基类复制构造函数作为默认行为调用?
所有基本子构造函数都调用父默认构造函数.这就是标准的定义方式.正如您所指出的,如果您希望派生类B调用A的复制构造函数,则必须明确地要求它
#include <iostream>
class A {
int a;
public:
A() {
std::cout << "A::Default constructor" << std::endl;
}
A(const A& rhs) {
std::cout << "A::Copy constructor" << std::endl;
}
};
class B : public A {
int b;
public:
B() {
std::cout << "B::Default constructor" << std::endl;
}
B(const B& rhs):A(rhs) {
std::cout << "B::Copy constructor" << std::endl;
}
};
int main(int argc, const char *argv[])
{
std::cout << "Creating B" << std::endl;
B b1;
std::cout << "Creating B by copy" << std::endl;
B b2(b1);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这是因为编译器无法知道每个不同的构造函数应该调用父节点的构造函数,因此我们有默认构造函数对于所有其他构造函数,您必须明确说明它们.
输出:
Creating B
A::Default constructor
B::Default constructor
Creating B by copy
A::Copy constructor
B::Copy constructor
Run Code Online (Sandbox Code Playgroud)
这就是隐式复制构造函数的定义方式(调用默认值没有意义).一旦定义了任何构造函数(复制或其他),它的正常自动行为就是调用默认的父构造函数,因此对于一个特定的用户定义构造函数更改它是不一致的.