构造函数/函数声明参数列表内的统一初始化

dme*_*dme 6 c++ constructor initialization uniform

我正在学习 C++ 中的类和 OOP 的一些基本知识。据我了解,初始化变量的首选现代方法是使用统一初始化。

在下面的简单类头示例中,使用统一初始化来初始化 3 个数据成员(长度、宽度和高度)。

为了保持一致性,我认为在构造函数声明中设置默认值时使用统一初始化可能是个好主意,但这不起作用,编译器(Debian Stretch 上的 gcc 6.3)会生成错误。从我所看到的来看,编译器认为大括号 {} 是构造函数定义主体的开始(显然不是,因为尚未添加右括号“)”)。

我承认这行不通,但出于好奇,有什么原因吗?我希望与我的代码保持一致,并尽可能使用统一的初始化。

谢谢。

#ifndef BOX_H
#define BOX_H

class Box
{

private:
    double length {1.0};
    double width {1.0};
    double height {1.0};

public:
    //constructor
    Box(double l = 1.0, double w = 1.0, double h = 1.0); //ok
    //Box(double l {1.0}, double w {1.0}, double h {1.0}); //Error

    double volume();
};

#endif
Run Code Online (Sandbox Code Playgroud)

编辑...感谢到目前为止的评论,但我不确定我是否理解为什么不能对默认参数使用统一初始化的原因。有人可以指点我一些标准的 C++ 文档吗?

例如,采用下面的基本程序,可以使用统一初始化将n初始化为 5 ,但是不能这样在函数头中将x初始化为默认参数(我使用带有 -std 的 gcc 6.3 =c++17)。为什么是这样?如果到目前为止我还没有理解帮助,我深表歉意。

#include <iostream>

void printNum(int x {1}) //error
{
    std::cout<<x<<"\n";
}

int main()
{
    int n {5};  //OK

    printNum(n);
}
Run Code Online (Sandbox Code Playgroud)

Sto*_*ica 6

这是一个语法限制。这个特定的语法元素在[dcl.fct] \xc2\xb63中描述:

\n\n
\n
\n参数声明子句:\n 参数声明列表opt ... opt \n 参数声明列表 , ...\n\n参数声明列表: \n 参数声明\n 参数声明-列表 ,参数声明\n\n参数声明:\n attribute-specifier-seq opt decl-specifier-seq 声明符 \n attribute-specifier-seq opt decl-specifier-seq declarator = 初始化子句\n attribute-specifier- seq opt decl-说明符-seq 抽象声明符opt \n 属性说明符-seq opt decl-说明符-seq 抽象声明符 opt = 初始化子句\n
\n
\n\n

需要注意的是,语法仅允许前面带有 . 的初始化子句出现=。我怀疑这是为了确保函数声明和对象声明之间没有歧义。例如,在块作用域中:

\n\n
Widget foo(CompA{}, CompB{});\n
Run Code Online (Sandbox Code Playgroud)\n\n

必须是一个对象声明,就像想要确保的统一初始化提案一样。允许 plain{}作为默认参数会使上面的内容变得不明确,并且我们只会将另一个令人烦恼的解析添加到集合中。所以=需要a。

\n\n

现在,至于为什么不允许在不太可能出现歧义的构造函数中使用它:如果无法支持更通用的用例,标准委员会实际上并不习惯允许非常受限的用例。

\n

  • 谢谢讲故事的人……这个解释确实有助于解决我心中的问题。感谢您指出一个具体示例来阐明您的观点。 (3认同)