语法解析:
C++ 编译器在解析
A b();
时,优先考虑将其解析为函数声明,而不是对象声明。具体来说:
- 函数声明:
A b();
被解析为声明了一个名为b
的函数,该函数没有参数,返回类型为A
。 - 对象声明:如果要创建一个
A
类的对象b
,应该使用A b;
或A b{};
解决方法
为了避免“最 vexing parse”问题,可以使用以下几种方法来明确表示创建一个对象:
-
不带括号:A b;
-
使用大括号初始化(C++11 及以后版本):
A b{};
-
使用等号初始化:
A b = A();
示例:
#include <iostream>
using namespace std;
class A {
public:
A() {
cout << "A constructor called" << endl;
}
};
int main() {
// 正确的方式:创建一个 A 类的对象
A a; // 不带括号
A b{}; // 使用大括号初始化
A c = A(); // 使用等号初始化
// 错误的方式:声明了一个返回类型为 A 的函数
A d(); // 这实际上是声明了一个函数
return 0;
}
运行上述代码时,你会看到以下输出:
A constructor called
A constructor called
A constructor called
详细解释
-
A a;
- 不带括号,明确表示创建一个
A
类的对象a
。 - 调用
A
的默认构造函数。
- 不带括号,明确表示创建一个
-
A b{};
- 使用大括号初始化,明确表示创建一个
A
类的对象b
。 - 调用
A
的默认构造函数。
- 使用大括号初始化,明确表示创建一个
-
A c = A();
- 使用等号初始化,明确表示创建一个
A
类的对象c
。 - 调用
A
的默认构造函数。
- 使用等号初始化,明确表示创建一个
-
A d();
- 被解析为声明了一个返回类型为
A
的函数d
,而不是创建一个A
类的对象。 - 因此,不会调用
A
的构造函数。
- 被解析为声明了一个返回类型为
最 vexing parse 问题:
A b();
被解析为声明了一个返回类型为 A
的函数,而不是创建一个 A
类的对象。
- 解决方法:
- 不带括号:
A b;
- 使用大括号初始化:
A b{};
- 使用等号初始化:
A b = A();
- 不带括号: