C++ Grand Parent 默认构造函数调用
C++ Grand Parent default constructor call
只要包含 Rect 默认构造函数,我就有以下代码可以正常运行。但是,如果我将其注释掉,希望它只是 'skip' 到 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;
}
当程序运行并编译时,我得到以下输出
...
Shape default called
Rect default called
Square constructor called.
Area: 100
我希望简单地删除 Rect
默认构造函数并获得
...
Shape default called
Square constructor called.
Area: 100
因为所有 rect 默认构造函数将做的就是坐在那里满足 clang 的错误。它无意做任何额外的事情。有办法实现吗?
您应该使用成员初始值设定项列表语法来使用您的参数调用适当的 Rect
构造函数:
Square(int width) : Rect(width, width)
{
printf("Square constructor called.\n");
}
请注意,您不需要手动分配给 this->width
和 this->height
,Rect
构造函数会为您完成此操作。
在构造函数主体中使用初始化列表而不是赋值的主要优点是,它可以避免对默认构造函数进行不必要的调用。详见this answer。
它还允许您继承没有默认构造函数的classes(并拥有它们的数据成员)。
如果你需要先对值做一些事情,那么在构造函数体中赋值是完全可以的,但是你的基础class(或成员class,如果你正在初始化一个数据成员) 必须有默认构造函数。
原因是每个数据成员的构造函数都必须(并且已经)在您的 class' 构造函数体开始执行之前被调用。初始化列表允许您根据您提供的参数选择调用哪个构造函数。如果您不在初始化列表中初始化数据成员,它将使用其默认构造函数构造(这就是必须声明它的原因),然后才能在构造函数主体中为其分配任何值。
只要包含 Rect 默认构造函数,我就有以下代码可以正常运行。但是,如果我将其注释掉,希望它只是 'skip' 到 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;
}
当程序运行并编译时,我得到以下输出
...
Shape default called
Rect default called
Square constructor called.
Area: 100
我希望简单地删除 Rect
默认构造函数并获得
...
Shape default called
Square constructor called.
Area: 100
因为所有 rect 默认构造函数将做的就是坐在那里满足 clang 的错误。它无意做任何额外的事情。有办法实现吗?
您应该使用成员初始值设定项列表语法来使用您的参数调用适当的 Rect
构造函数:
Square(int width) : Rect(width, width)
{
printf("Square constructor called.\n");
}
请注意,您不需要手动分配给 this->width
和 this->height
,Rect
构造函数会为您完成此操作。
在构造函数主体中使用初始化列表而不是赋值的主要优点是,它可以避免对默认构造函数进行不必要的调用。详见this answer。
它还允许您继承没有默认构造函数的classes(并拥有它们的数据成员)。
如果你需要先对值做一些事情,那么在构造函数体中赋值是完全可以的,但是你的基础class(或成员class,如果你正在初始化一个数据成员) 必须有默认构造函数。
原因是每个数据成员的构造函数都必须(并且已经)在您的 class' 构造函数体开始执行之前被调用。初始化列表允许您根据您提供的参数选择调用哪个构造函数。如果您不在初始化列表中初始化数据成员,它将使用其默认构造函数构造(这就是必须声明它的原因),然后才能在构造函数主体中为其分配任何值。