我的问题很简单。我们何时需要默认构造函数? 请参考以下代码:
class Shape
{
int k;
public:
Shape(int n) : k(n) {}
~Shape() {}
};
class Rect : public Shape
{
int l;
public:
Rect(int n): l(n)
{} //error C2512: 'Shape' : no appropriate default constructor available
~Rect() {}
};
为什么编译器不会在类Rect中隐式生成零参数默认构造函数?
据我所知,如果一个类(Rect)派生自另一个具有默认构造函数(隐式生成或显式提供)的类(Shape),则默认构造函数应由编译器生成。
答案 0 :(得分:23)
如果使用参数创建自己的构造函数,则不会合成默认构造函数。既然你给了Shape
自己的构造函数,那么你现在必须明确地写出一个默认的Shape
构造函数:
class Shape
{
int k;
public:
Shape() : k(0) {}
Shape(int n) : k(n) {}
~Shape() {}
};
(您可以省略空的~Rect() {}
定义,因为这些定义将被合成。)
但是,在我看来,你不希望想要这里的Shape的默认构造函数。 Rect
正确构建Shape
基数:
class Shape
{
int area; // I've had to guess at what this member means. What is "k"?!
public:
Shape(const int area)
: area(area)
{}
};
class Rect : public Shape
{
int l;
int w;
public:
Rect(const int l, const int w)
: Shape(l*w)
, l(l)
, w(w)
{}
};
另请注意,此示例为oft cited as an abuse of OO。考虑一下真的是否需要继承。
答案 1 :(得分:11)
如果没有定义其他构造函数,则只会由编译器自动生成默认构造函数。无论任何继承。
您还需要通过调用:
来构建基类Rect( int n ) : Shape( n ), l(n)
{
}
答案 2 :(得分:2)
当且仅当您没有明确声明任何ctors时,编译器才会定义默认的ctor。
请注意,重要的是声明构造函数,而不一定是定义它。例如,声明私有ctor并且从不定义它是相当常见的,以防止编译器隐式定义任何其他。
编辑:另请注意,C ++ 11具有=default
语法,用于处理与您类似的情况。
答案 3 :(得分:2)
有关C ++ WRT构造函数的完整行为,请参阅此内容:http://en.wikipedia.org/wiki/Default_constructor
简单的答案是,如果指定构造函数,编译器将不会为您创建默认构造函数。
此规则也适用于Java。
答案 4 :(得分:0)
仅当您尚未定义任何其他构造函数时,才会生成默认构造函数。
据说,如果你需要在类中进行一些特殊的初始化,那么默认的构造函数就不会做正确的事情。
答案 5 :(得分:0)
当您为Shape定义一个期望整数的构造函数时,您已通过这样做覆盖了默认构造函数。因此,如果扩展Shape,则必须将整数值传递给超类。
答案 6 :(得分:0)
编译器会在您未定义任何构造函数时生成默认构造函数。但是如果你已经定义了任何带有参数的构造函数。编译器将使用该构造函数,并且不会生成零参数的默认构造函数。