如果我有一个带有复杂数据成员的基类,比如说char*
,并且在我的继承链的末尾,我还有另一个具有相同类型DM的类,那么我是否必须实现CCTORs所有其他课程都在进行中?
例如:
动物类:
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..}
}
即使只有Mammal
作为数据成员,我是否仍需要在int
中实现CCTOR?
基本上我的问题是:当复制一个复杂的对象(由多个类构建)时,编译器是否分别激活每个部分的CCTOR?
编辑:
要清楚,我想复制一个Horse
对象。如果我按上述方式编写代码,其名称也会被深复制吗?
答案 0 :(得分:3)
不,你不知道。默认情况下(如Mammal),副本构造函数将依次调用每个基类的副本构造函数,然后依次调用每个成员变量的副本构造函数。因此,哺乳动物的副本构造函数很好。
请注意我关于“每个成员变量的复制构造函数”的观点。当然char*
的副本构造函数什么都不做-但是,如果将char*
用合适的副本构造函数包装在一个类中,则Animal
和Horse
都可以将该类用于他们的成员变量-不需要他们自己的副本构造函数。
事实上,当然已经为您提供了std::string
(但我认为您实际上还有一个更复杂的案例)。
答案 1 :(得分:2)
即使它只有一个int作为数据成员,我仍需要在哺乳动物中实现CCTOR吗?
否。
在复制复杂对象(由多个类构建)时,编译器是否会分别激活每个部分的CCTOR?
是的
例如参见https://en.cppreference.com/w/cpp/language/copy_constructor#Implicitly-defined_copy_constructor:
对于非联合类类型(
class
和struct
),构造函数在其基类和非静态成员中执行对象基和成员的完整成员副本初始化顺序,使用直接初始化。
(强调我的。)
这就像基础对象只是类的另一个成员一样。如果Animal
的工作方式像是正确的值类型(具有做正确的事情的复制构造函数,赋值运算符和析构函数),则在Mammal
之类的派生类中无需执行任何特殊操作。 / p>
但是,请注意,现代C ++风格努力使成员管理不受构造函数的限制。也就是说,例如Horse
不应在其构造函数(和析构函数)中为color
分配(和取消分配)内存。
每个成员都应该自己管理(您必须将color
的类型更改为其他类型,例如std::string
),因此由编译器生成的默认副本构造函数和析构函数可以正常工作。
答案 2 :(得分:0)
您遇到问题的类成员是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;
};