提问人:Daniel 提问时间:6/1/2019 最后编辑:Guy AvrahamDaniel 更新时间:11/6/2023 访问量:1620
是否有必要为派生类创建复制构造函数?
Is it necessary to create a Copy Constructor for derived classes?
问:
如果我有一个具有复杂数据成员的基类,比方说,在我的继承链的末尾,我有另一个具有相同类型 DM 的类,我是否必须实现所有其他类的 CCTOR(复制构造函数)?char*
例如:
动物类:
class Animal
{
int age;
char* name;
Animal() { ... }
Animal(const Animal &animal) { ..deep copying name..}
}
哺乳动物类:
class Mammal : public Animal
{
int height;
Mammal() { ... }
}
马类:
class Horse : public Mammal
{
char* color;
Horse() { ... }
Horse(const Horse &horse ) { ..deep copying color..}
}
我是否需要在 中实现 CCTOR,即使它只有一个作为数据成员?Mammal
int
基本上我的问题是:当复制一个复杂的对象(由多个类构建)时,编译器是否分别激活每个部分的 CCTOR?
编辑:
为了清楚起见,我想复制一个对象。如果我按上面的方式编写代码,它的名字也会被深度复制吗?Horse
答:
我是否需要在 Mammal 中实现 CCTOR,即使它只有一个 int 作为数据成员?
不。
复制复杂对象(由多个类生成)时,编译器是否分别激活每个部分的 CCTOR?
是的。
例如,参见 https://en.cppreference.com/w/cpp/language/copy_constructor#Implicitly-defined_copy_constructor:
对于非联合类类型 ( 和 ),构造函数使用直接初始化按对象的初始化顺序执行对象的基和非静态成员的完整成员复制。
class
struct
(强调我的。
这就像基对象只是类的另一个成员。如果像适当的值类型一样工作(具有执行正确操作的复制构造函数、赋值运算符和析构函数),则不必在派生类中执行任何特殊操作,例如 .Animal
Mammal
但请注意,现代 C++ 样式努力将成员管理排除在构造函数之外。也就是说,例如 不应关注在其构造函数(和析构函数)中分配(和取消分配)内存。Horse
color
相反,每个成员都应该管理自己(例如,您必须将 的类型更改为其他类型),因此编译器生成的默认复制构造函数和析构函数可以正常工作。color
std::string
不,你没有。默认情况下(与 Mammal 一样),复制构造函数将调用每个基类的复制构造函数(按顺序),然后调用每个成员变量的复制构造函数(按顺序)。因此,Mammal 的复制构造函数很好。
请注意我关于“每个成员变量的复制构造函数”的观点。当然,的复制构造函数不做任何事情 - 但是如果你用合适的复制构造函数包装在一个类中,那么 并且都可以将该类用于他们的成员变量 - 并且不需要他们自己的复制构造函数。char*
char*
Animal
Horse
事实上,当然,已经为您提供了(但我认为您在现实中有一个更复杂的情况)。std::string
您拥有的有问题的类成员是原始指针。char*
在惯用的 c++ 中,你可以改用 std
::string 来解决这个问题,因此你不需要指定任何构造函数:
class Animal
{
int age;
std::string name;
Animal() = default; // not really neccessary, just for demonstration
// purpose
Animal(const Animal &animal) = default; // not really neccessary, just for
// demonstration purpose
};
class Mammal : public Animal
{
int height;
};
class Horse : public Mammal
{
std::string color;
};
评论
std::string
char*