重载构造函数中的成员初始化

Member Initialization in overloaded constructor

我有一个基本的语义相关疑问,我无法得到澄清。在陈述问题之前,我会写下最少的代码来解释清楚。

在Constants.hpp

#pragma once
enum class OpenglESVersion{
    OES1,
    OES2
};

在Cone.hpp中,我有一个枚举成员

OpenglESVersion esVersion;

Cone.cpp 中以枚举作为参数的重载构造函数定义

Cone::Cone(const OpenglESVersion version) : rotationAngle(0), scale(1), esVersion(version) {}

现在在我的 RenderingEngine.cpp 中实例化 Cone 对象时:

Cone cone(OpenglESVersion::OES2);

我收到语法错误:

No type named 'OES2' in 'OpenglESVersion'

现在,如果我将我的对象实例更新为:

Cone cone{OpenglESVersion::OES2};

现在可以了。

我的编译器是 libc++[支持 c++11 的 LLVM c++ 标准库] ,方言是 c++11[-std=c++11] 我正在使用 XCode.

现在我怀疑: 我通过资源来澄清这个概念。过去我在学校使用 pre c++11 版本,遵循 2008 年印刷的 Bjarne 的 C++ 编程书,所以这就是为什么我没有在书中找到这个 "curly" 初始化语法的原因 c++11 出来了稍后。

我尝试了 google,但不确定要搜索什么关键字,但后来最常见的主题名称指向 "list initialization"。几乎所有资源都涵盖了 c++11 中这种新语法的优势,但我从来没有弄清楚为什么普通圆括号被视为语法错误,因为那里有很多资源,示例显示也使用圆括号和大括号组合在解释差异时,他们使用的是原始类型的示例,例如:

int x(4);
int x{4};

所以这又没有为我澄清这个概念。现在我来这里是为了了解或获得一些适当的 link 或解释我的疑问的资源的指导。

编辑: 对于任何重载版本都会发生这种情况,假设构造函数的 int 参数重载版本。

Cone::Cone(const int fooVariable) : fooMember(fooVariable){}

唯一有效的代码是:

Cone cone{8};

我明白了

Expected parameter declarator, Expected ')'

对于Cone cone(8);

如果出于好奇我在 Cone class 本身的成员函数内部实例化,就像编译器不抛出任何语法或某些错误一样,这种行为不会发生:

void Cone::Test(){
    Cone cone(OpenglESVersion::OES2);
}

编辑更新 2: 我想我还有另一个测试用例,它肯定会缩小范围。所以这是模式:

class RenderingEngine
{
private:
    Cone cone(OpenglESVersion::OES2);
};

所以我将 Cone 对象声明并实例化为 RenderingEngine class 的成员。那么这可能是导致我的问题的原因吗?因为如果我这样做

Cone cone(OpenglESVersion::OES2);

在 RenderingEngine/Outside class 实现的任何成员函数中然后它就可以工作。所以必须有一些基本规则,我违反了非原始成员变量可以声明和实例化的内容和方式。

C++11 引入了成员初始化。

不支持括号以避免最麻烦的解析,因此您可以使用 {..}= 语法:

class RenderingEngine
{
private:
    Cone cone{OpenglESVersion::OES2};
};

class RenderingEngine
{
private:
    Cone cone = Cone(OpenglESVersion::OES2); // With =, you can use parent on right side
};