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

Posted

技术标签:

【中文标题】重载构造函数中的成员初始化【英文标题】:Member Initialization in overloaded constructor 【发布时间】:2017-09-11 04:02:25 【问题描述】:

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

在常量.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) 

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

Cone cone(OpenglESVersion::OES2);

我收到语法错误:

“OpenglESVersion”中没有名为“OES2”的类型

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

Cone coneOpenglESVersion::OES2;

现在可以了。

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

现在我的疑问是: 我通过资源来澄清这个概念。过去,我在学校使用过 c++11 之前的版本,遵循 Bjarne 于 2008 年出版的 C++ 编程书,所以这就是为什么我没有在 c++11 的书中发现这种“卷曲”初始化语法后来出现的原因。

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

int x(4);
int x4;

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

我的编译器是否使用了圆括号初始化语法 过时了吗? 它并没有过时,但在 c++ 中从未得到支持? 我错误地声明和定义了重载的构造函数? 是否不支持通过圆括号语法初始化成员? 为什么?

编辑: 任何重载版本都会发生这种情况,比如说构造函数的 int 参数重载版本。

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

只有代码有效:

Cone cone8;

我明白了

预期的参数声明符,预期的')'

Cone cone(8);

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

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

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

class RenderingEngine

private:
    Cone cone(OpenglESVersion::OES2);
;

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

Cone cone(OpenglESVersion::OES2);

在 RenderingEngine/Outside 类实现的任何成员函数中,它都可以工作。因此,在声明和实例化非原始成员变量的内容和方式方面,我必须违反一些基本规则。

【问题讨论】:

看起来像是“最令人头疼的解析”。 Can't reproduce @PasserBy 嗨,语法 Cone con(OpenglESVersion::OES2);我尝试在同一个 Cone 类/文件中的成员函数内部调用,这意味着编译器不会抛出任何错误。我很想检查一下。但是,如果像我的问题一样从不同的类和文件实例化,那么就会发生这种情况。你可以试试吗? 我猜OpenglESVersion已经在opengl中定义了,我没有安装opengl,无法测试 这是一个未内置的自定义枚举。我将重构后的枚举重命名为 FOO。同样的错误。这不仅适用于枚举。任何重载版本都会发生这种情况,比如说构造函数的 int 参数重载版本。 【参考方案1】:

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

不支持括号以避免最麻烦的解析,所以你可以使用..=语法:

class RenderingEngine

private:
    Cone coneOpenglESVersion::OES2;
;

class RenderingEngine

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

【讨论】:

嗨。谢谢你。在我的示例中,成员初始化如何变得模棱两可? 类似这样的:Cone cone(Cone());

以上是关于重载构造函数中的成员初始化的主要内容,如果未能解决你的问题,请参考以下文章

11.6 C++构造函数重载

11.6 C++构造函数重载

类的默认成员函数

c++中拷贝构造函数和赋值运算符重载本质上一样么

构造函数,重载与重写的区别,静态成员和方法

构造函数的定义和构造函数的重载