【问题标题】:Why no other constructor is being allowed?为什么不允许其他构造函数?
【发布时间】:2016-09-28 09:12:54
【问题描述】:

我正在学习 initializer list 并了解到必须使用它来初始化 const 成员,因为您无法使用默认构造函数或参数化构造函数对其进行初始化。

class Foo
{
private:
    const int y;            
public:         
    Foo(int yy) :y(yy){}        
    int getY();
};

现在假设如果我有另一个成员int x; 不是 const,为什么我不能使用默认构造函数初始化它,这个限制背后的想法是什么?

给出错误的代码:

class Foo
{
private:
    const int y;    
    int x;
public:     
    Foo(int yy) :y(yy){}
    Foo()
    {
        x = 100;
    }
    int getY();
};

【问题讨论】:

  • "为什么我不能使用默认构造函数来初始化它" 可以吗?能说清楚一点吗?
  • 您可以在默认构造函数中初始化您喜欢的任何成员。我不明白这个问题。请为您认为工作的内容发布 MCVE。
  • 顺便说一句,“因为您无法使用默认构造函数或参数化构造函数对其进行初始化。”听起来您对“默认构造函数”一词有误解。
  • mcve 做得很好。我已经添加了对我的回答的回复,描述了您的代码问题。
  • 你可能还没有在你的书/课程中介绍过这个,但也有一种间接的方式。一个构造函数可以委托到另一个构造函数,而不是有一个初始化列表。然后,const 成员必须由第二个委托构造函数初始化。

标签: c++ initializer-list


【解决方案1】:

我正在学习初始化列表并了解到必须使用它来初始化 const 成员,因为您无法使用默认构造函数或参数化构造函数对其进行初始化。

可以在默认构造函数和任何参数化构造函数的成员初始化器列表中初始化常量成员。 (默认构造函数是可以不带参数调用的构造函数。)

现在假设我有另一个成员 int x;不是 const,为什么我不能使用默认构造函数来初始化它,这个限制背后的想法是什么?

您可以在默认构造函数中初始化任意数量的成员(可能存在一些实现定义的限制,但与此问题无关)。没有你描述的这种限制。

Demo,有两个成员的类,都在默认构造函数中初始化:

struct Foo {
    const int y;
    int       x;
    Foo(): y(1), x(100){}
};

编辑 mcve。

给出错误的代码:

class Foo
{
private:
    const int y;    
    int x;
public:     
    Foo(int yy) :y(yy){}
    Foo()
    {
        x = 100;
    }
    int getY();
};

所有 构造函数必须初始化 const 成员。您的参数化构造函数会初始化 y,但默认构造函数不会。这就是为什么它不起作用。有关工作示例,请参见我上面的演示。

PS。您的参数化构造函数没有初始化 x,但没关系:x 不是 const,因此您可以稍后为其赋值。


在我的代码中,如果我有一个像 Foo(int xx) { x = xx;}这样的参数化构造函数

不会报错

这个程序:

struct Foo {
    const int y;
    int       x;
    Foo(int xx) { x = xx;}
};

在标准 C++ 中格式不正确。如果您的编译器在没有警告的情况下接受它,则它不符合标准。

【讨论】:

  • “可能有一些实现定义的限制,但与这个问题无关” 今日趣事:C++14 的附录 B 建议将此限制设为至少 6144。
  • 当你说所有构造函数都必须初始化 const 成员时。
  • 在我的代码中,如果我有一个参数化的构造函数,比如 Foo(int xx) { x = xx;}
  • 它不会给出任何错误,并且您说所有构造函数都必须初始化 const 成员。
  • @SumeetSingh 不,答案是完全正确的。每个const 内置变量都需要在每个构造函数中进行初始化。如果您认为这不会发生在您身上,请向 MCVE 提出新问题。
【解决方案2】:

不清楚你想要完成什么。 以下代码简单编译

class Foo
{
private:
    int _nonConst;
    const int _const;

public:
    Foo() : _const(10), _nonConst(11)
    {

    }

    Foo(int x) : _const(x), _nonConst(x)
    {

    }
};

【讨论】:

    【解决方案3】:

    我不确定我是否正确理解了这个问题。总结一下你能做什么和不能做什么:

    // .h
    class MyClass
    {
    private:
        int x;
        const int y;
    
    public:
        MyClass();
        MyClass(int initValue);
    };
    
    // .cpp
    // The following is legal
    MyClass::MyClass() 
    : x(0), y(0) 
    {}     
    
    // Alternatively, the following is legal too. 
    MyClass::MyClass() 
    : y(0) 
    { 
        x = 0; 
    }   
    
    // This is not legal: y cannot be initialized that way as it is const.
    // No problem for x though.
    MyClass::MyClass() 
    { 
        x = 0; 
        y = 0; // You cannot do that
    } 
    
    // The following is legal
    MyClass::MyClass(int initValue) 
    : x(initValue), y(initValue) 
    {}     
    
    // Alternatively, the following is legal too. 
    MyClass::MyClass(int initValue) 
    : y(initValue) 
    { 
        x = initValue; 
    }   
    
    // This is not legal: y cannot be initialized that way as it is const.
    // No problem for x though.
    MyClass::MyClass(int initValue) 
    { 
        x = initValue; 
        y = initValue; // You cannot do that
    } 
    

    当然,每个声明的签名只能有一个 CTor。上面的例子是 3 个备选方案 - 2 个合法的和 1 个非法的 - 每个声明的签名。

    【讨论】:

      猜你喜欢
      • 2013-03-03
      • 1970-01-01
      • 1970-01-01
      • 2018-08-16
      • 2015-06-06
      • 1970-01-01
      • 2019-06-01
      • 2015-07-14
      相关资源
      最近更新 更多