【问题标题】:When do we need to have a default constructor?我们什么时候需要有一个默认构造函数?
【发布时间】:2011-03-31 11:15:39
【问题描述】:

我的问题很简单。我们什么时候需要有一个默认构造函数? 请参考以下代码:

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),则默认构造函数应该由编译器生成。

【问题讨论】:

  • 构造 Rect 对象并使用它的部分在哪里?可能你创建它就像'Rect rec;'这需要一个默认的构造函数。
  • IIRC 如果您不指定构造函数,编译器将为您创建一个默认构造函数。但如果你指定一个,它只会有那个。
  • ctor == 构造函数...啊哈!
  • @poweroy:是的,你是对的;但我假设“Rect rec”将使用编译器提供的默认 ctor
  • @Tomalak:我想知道 wat ctor 的含义,并发现(通过谷歌搜索)它是构造函数的常见缩写。我不知道。

标签: c++ language-lawyer


【解决方案1】:

如果您使用参数创建自己的构造函数,则不会合成默认构造函数。既然你给了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。在此考虑您是否真的需要继承。

【讨论】:

  • 所以,如果我们有一个parameterized ctor,那么我们必须/必须明确地创建一个default constructor。为什么编译器implicitly 这次不为我们创建一个?
  • @Jos 如果您不想要一个默认构造函数,您没有 创建一个默认构造函数。但是,如果您确实想要一个,则必须自己提供(或将其设为= default)。为什么?可能是因为如果你想要一个非默认构造函数,那么默认构造函数对那个类来说不太可能有意义,而且人们很容易没有意识到它是无论如何生成的,从而导致出现错误的风险。这正是上面示例中的情况。顺便说一句,请不要对英文短语使用代码格式。
【解决方案2】:

只有在没有定义其他构造函数的情况下,编译器才会自动生成默认构造函数。无论任何继承。

你还需要通过调用来构造你的基类:

Rect( int n ) : Shape( n ), l(n)
{
}

【讨论】:

    【解决方案3】:

    查看 C++ WRT 构造函数的完整行为:http://en.wikipedia.org/wiki/Default_constructor

    简单的答案是,如果您指定构造函数,编译器不会为您创建默认构造函数。

    这条规则也适用于 Java。

    【讨论】:

      【解决方案4】:

      当且仅当您没有显式声明任何 ctor 时,编译器才会定义默认 ctor。

      请注意,重要的是声明构造函数,而不一定要定义它。例如,声明一个私有 ctor 并且从不定义它是相当常见的,以防止编译器隐式定义任何其他 ctor。

      编辑:另请注意,C++11 有一个 =default 语法来处理像你这样的情况。

      【讨论】:

      • > 声明一个私有 ctor,并且从不定义它,以防止编译器隐式定义任何其他 ctor。你能举个例子解释一下吗?
      • @Phalgun:我想我可以,但我犹豫不决——C++11 添加了新代码中通常首选的= delete; 语法:class foo { int foo() = delete; }; 将阻止编译器定义foo 的默认 ctor。您可以通过声明私有 ctor 来获得相同的效果,但 = delete; 语法更直接地表达了意图,因此我建议您使用它,除非您确实需要与旧的(c++11 之前的)编译器兼容。跨度>
      • 如果我在类中提供参数化构造函数,这会阻止编译器定义默认构造函数。在这种情况下,编译器是否仍会提供隐式复制构造函数和复制赋值构造函数,以防我根本没有提供任何构造函数?
      • @Phalgun:这是正确的——定义默认构造函数不会影响是否隐式声明复制 ctor 和/或复制赋值运算符。
      【解决方案5】:

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

      【讨论】:

        【解决方案6】:

        仅当您没有定义任何其他构造函数时才会生成默认构造函数。

        假设,如果您需要在类中进行一些特殊的初始化,默认构造函数不会做正确的事情。

        【讨论】:

          【解决方案7】:

          当您为 Shape 定义一个期望整数的构造函数时,您已经通过这样做覆盖了默认构造函数。因此,如果您扩展 Shape,您必须将一个整数值传递给超类。

          【讨论】:

            猜你喜欢
            • 2019-03-01
            • 2011-03-30
            • 2011-09-27
            • 2012-12-25
            • 2011-09-20
            • 2023-04-09
            • 2019-06-12
            • 2018-07-01
            相关资源
            最近更新 更多