只要我包含Rect默认构造函数,我就会运行以下代码。但是,如果我发表评论希望它只是“跳过”到Shape默认构造函数,它就无法编译。
#include <cstdio>
class Shape
{
public:
Shape()
{
printf("Shape default called\n");
}
};
class Rect : public Shape
{
public:
int width;
int height;
Rect()
{
printf("Rect default called\n");
}
Rect(int width, int height)
{
this->width = width;
this->height = height;
}
int area()
{
return width*height;
}
};
class Square : public Rect
{
public:
Square(int width)
{
printf("Square constructor called.\n");
this->width = width;
this->height = width;
}
};
int main(int argv, char** argc)
{
printf("...\n");
Square r = Square(10);
printf("Area: %d\n", r.area());
return 0;
}
当程序运行并编译时,我得到以下输出
...
形状默认名为
Rect默认名为
方形构造函数叫。
面积:100
我希望简单地删除Rect
默认构造函数并获取
...
形状默认名为
方形构造函数叫。
面积:100
因为所有rect默认构造函数都会坐在那里以满足clang的错误。它不打算做任何额外的事情。有没有办法实现这个目标?
答案 0 :(得分:2)
您应该使用成员初始化列表语法来使用您的参数调用适当的Rect
构造函数:
Square(int width) : Rect(width, width)
{
printf("Square constructor called.\n");
}
请注意,您不需要手动分配到this->width
和this->height
,Rect
构造函数会为您执行此操作。
在构造函数体中使用初始化列表而不是赋值的主要优点是它允许避免对默认构造函数的不必要的调用。有关详细说明,请参阅this answer。
它还允许您继承(并且拥有)没有默认构造函数的类的数据成员。
如果您需要先对值执行某些操作,那么在构造函数体中分配值是完全正确的,但是您的基类(或成员类,如果您正在初始化数据成员)必须具有默认构造函数
这样做的原因是每个数据成员的构造函数必须在您的课程之前调用(并且被调用)。构造函数体开始执行。初始化列表允许您根据您提供的参数选择调用哪个构造函数。如果您没有初始化初始化列表中的数据成员,那么它将使用其默认构造函数构造(这就是为什么必须声明它),然后才能在构造函数体中为其分配任何值。