我正在学习有关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
EDIT ....到目前为止,感谢您的评论,但是我不确定我不能理解为什么无法对默认参数使用统一初始化的原因。有人可以指出我一些标准的C ++文档吗?
例如,使用下面的基本程序,可以使用均匀初始化将 n 初始化为5。 不可以像这样将 x 初始化为函数标头中的默认参数(我正在将gcc 6.3与-std = c ++ 17一起使用)。为什么是这样?抱歉,如果到目前为止我还不了解帮助。
#include <iostream>
void printNum(int x {1}) //error
{
std::cout<<x<<"\n";
}
int main()
{
int n {5}; //OK
printNum(n);
}
答案 0 :(得分:3)
这是语法上的限制。此特定的语法元素在[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{});
必须是对象声明,就像要确保的统一初始化建议一样。允许使用简单的{}
作为默认参数将使上面的内容变得模棱两可,而我们只有另一个烦人的解析器可以添加到集合中。因此,需要=
。
现在,关于为什么不能在不太可能出现歧义的构造函数中不允许这样做的问题:如果无法支持更通用的用例,标准委员会实际上就不会允许使用非常受限的用例。