constructor/function 声明参数列表中的统一初始化
Uniform Initialization inside constructor/function declaration parameter list
我正在学习 C++ 中有关 classes 和 OOP 的一些基本知识。根据我的阅读,初始化变量的首选现代方法是使用统一初始化。
在下面的简单 class 头示例中,统一初始化用于初始化 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
编辑....感谢到目前为止的评论,但我不确定我是否理解不能对默认参数使用统一初始化的原因。有人可以指点我一些标准的 C++ 文档吗?
比如下面这个基本程序,用[=27=初始化n值为5就可以了]uniform initialization 但是 not 可以像这样初始化 x函数头中的默认参数(我使用的是带有 -std=c++17 的 gcc 6.3)。为什么是这样?如果到目前为止我还没有理解帮助,请道歉。
#include <iostream>
void printNum(int x {1}) //error
{
std::cout<<x<<"\n";
}
int main()
{
int n {5}; //OK
printNum(n);
}
这是一个语法限制。 [dcl.fct] ¶3:
中描述了这个特定的语法元素
parameter-declaration-clause:
parameter-declaration-listopt ...opt
parameter-declaration-list , ...
parameter-declaration-list:
parameter-declaration
parameter-declaration-list , parameter-declaration
parameter-declaration:
attribute-specifier-seqopt decl-specifier-seq declarator
attribute-specifier-seqopt decl-specifier-seq declarator = initializer-clause
attribute-specifier-seqopt decl-specifier-seq abstract-declaratoropt
attribute-specifier-seqopt decl-specifier-seq abstract-declaratoropt = initializer-clause
需要注意的是,只有在初始化子句前面有 =
时,语法才允许出现初始化子句。我怀疑这是为了确保函数声明和对象声明之间没有歧义。例如,在块范围内:
Widget foo(CompA{}, CompB{});
必须是对象声明,就像要确保的统一初始化提案一样。允许普通的 {}
作为默认参数会使上面的内容变得模棱两可,我们只会将另一个令人烦恼的解析添加到集合中。所以需要=
。
现在,至于为什么不允许在不太可能出现歧义的构造函数中使用它:如果不能支持更通用的用例,标准委员会实际上并不习惯允许非常受限的用例。
我正在学习 C++ 中有关 classes 和 OOP 的一些基本知识。根据我的阅读,初始化变量的首选现代方法是使用统一初始化。
在下面的简单 class 头示例中,统一初始化用于初始化 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
编辑....感谢到目前为止的评论,但我不确定我是否理解不能对默认参数使用统一初始化的原因。有人可以指点我一些标准的 C++ 文档吗?
比如下面这个基本程序,用[=27=初始化n值为5就可以了]uniform initialization 但是 not 可以像这样初始化 x函数头中的默认参数(我使用的是带有 -std=c++17 的 gcc 6.3)。为什么是这样?如果到目前为止我还没有理解帮助,请道歉。
#include <iostream>
void printNum(int x {1}) //error
{
std::cout<<x<<"\n";
}
int main()
{
int n {5}; //OK
printNum(n);
}
这是一个语法限制。 [dcl.fct] ¶3:
中描述了这个特定的语法元素parameter-declaration-clause: parameter-declaration-listopt ...opt parameter-declaration-list , ... parameter-declaration-list: parameter-declaration parameter-declaration-list , parameter-declaration parameter-declaration: attribute-specifier-seqopt decl-specifier-seq declarator attribute-specifier-seqopt decl-specifier-seq declarator = initializer-clause attribute-specifier-seqopt decl-specifier-seq abstract-declaratoropt attribute-specifier-seqopt decl-specifier-seq abstract-declaratoropt = initializer-clause
需要注意的是,只有在初始化子句前面有 =
时,语法才允许出现初始化子句。我怀疑这是为了确保函数声明和对象声明之间没有歧义。例如,在块范围内:
Widget foo(CompA{}, CompB{});
必须是对象声明,就像要确保的统一初始化提案一样。允许普通的 {}
作为默认参数会使上面的内容变得模棱两可,我们只会将另一个令人烦恼的解析添加到集合中。所以需要=
。
现在,至于为什么不允许在不太可能出现歧义的构造函数中使用它:如果不能支持更通用的用例,标准委员会实际上并不习惯允许非常受限的用例。