为什么隐式复制构造函数调用基类复制构造函数,而定义的复制构造函数则不调用?
考虑一个类层次结构,其中 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;
}
输出:
Creating B
A::Default constructor
B::Default constructor
Creating B by copy
A::Copy constructor
如果用户在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;
}
输出:
Creating B
A::Default constructor
B::Default constructor
Creating B by copy
A::Default constructor
B::Copy constructor
我的问题是,为什么用户定义的复制构造函数不调用基类复制构造函数作为默认行为?
Consider a class hierarchy where A
is the base class and B
derives from A
.
If the copy constructor is not defined in B
, the compiler will synthesize one. When invoked, this copy constructor will call the base class copy constructor (even the synthesized one, if none has been provided by the user).
#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;
}
Output:
Creating B
A::Default constructor
B::Default constructor
Creating B by copy
A::Copy constructor
If the user defines its own copy constructor in B
, when invoked, this copy constructor will call the base class default constructor, unless a call to the base class copy constructor is explicitly present (e.g. in the initialization list).
#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;
}
Output:
Creating B
A::Default constructor
B::Default constructor
Creating B by copy
A::Default constructor
B::Copy constructor
My question is, why doesn't the user defined copy constructor call the base class copy constructor as a default behavior?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
所有基子构造函数都调用父默认构造函数。这就是标准的定义方式。正如您所指出的,如果您希望派生类 B 调用 A 的复制构造函数,则必须显式请求它,
这是因为编译器无法知道每个不同的构造函数应该调用父类的哪个构造函数,因此我们有默认构造函数 对于所有其他构造函数,您必须明确声明它们。
输出:
All base child constructors call the parent default constructor. This is how the standard is defined. As you pointed out if you wanted the derive class B to call A's copy constructor you have to explicitly ask for it
This is so because the compiler can't know for each different constructor which constuctor of the parent should be called and hence we have the default constructors For all others you have to explicitly state them.
Output:
这就是隐式复制构造函数的定义方式(调用默认值是没有意义的)。一旦定义任何构造函数(复制或其他),其正常的自动行为就是调用默认的父构造函数,因此为一个特定的用户定义构造函数更改该构造函数将是不一致的。
That's just the way the implicit copy constructor is defined (it wouldn't make sense calling the default). As soon as you define any constructor (copy or otherwise) its normal automatic behavior is to call the default parent constructor, so it would be inconsistent to change that for one specific user-defined constructor.
简单(可能是陈词滥调)的答案是因为你没有告诉它。由于您正在编写派生的复制构造函数,因此您可以完全控制它的行为方式。未能指定对基类的调用,编译器会生成代码以通过调用基类默认构造函数来初始化基类。
The simple (possibly trite) answer is because you didn't tell it to. Since you are writing the derived copy constructor, you completely control how it behaves. Failure to specify a call to the base and the compiler generates code to initialize the base class by calling the base classes default constructor.