我们何时需要默认构造函数?

时间:2011-03-31 11:15:39

标签: c++ language-lawyer

我的问题很简单。我们何时需要默认构造函数? 请参考以下代码:

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() {}
};
  1. 为什么编译器不会在类Rect中隐式生成零参数默认构造函数?

  2. 据我所知,如果一个类(Rect)派生自另一个具有默认构造函数(隐式生成或显式提供)的类(Shape),则默认构造函数应由编译器生成。

7 个答案:

答案 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)

编译器会在您未定义任何构造函数时生成默认构造函数。但是如果你已经定义了任何带有参数的构造函数。编译器将使用该构造函数,并且不会生成零参数的默认构造函数。