Most vexing parse (最烦人的解析)

Most vexing parse 在 Scott Meyers 在 Effective STL(2001)中 首次使用 。它在 C++ language standard 的 8.2节中正式定义。

Example with classes

An example is:

#include <iostream>

class Timer {
public:
	Timer(){};
};

class TimeKeeper {
public:
	TimeKeeper(const Timer& t){};

	int get_time(){return 0;};
};

int main() {
	TimeKeeper time_keeper(Timer());
	return time_keeper.get_time();
}

TimeKeeper time_keeper(Timer());似乎模棱两可,因为它可以解释为

  • 一个类型为TimeKeeper的变量名为time_keeper,用Timer类的匿名实例初始化
  • 一个函数名为time_keeper的函数声明,返回值类型为TimeKeeper ,并具有一个(未命名)参数,该参数是指向函数的指针,该函数返回Timer类型的对象(并且不输入任何内容) (See Function object #In C and C++#

大多数程序员期望第一个,但是C ++标准要求将其解释为第二个。例如,g++ 给出以下错误消息:

$ g ++ -c time_keeper.cc time_keeper.cc:在函数’int main()‘中:
time_keeper.cc : 15:错误:请求’time_keeper’中的成员’get_time’,它
是非类类型’TimeKeeper(Timer) (*)())’

在这里插入图片描述在这里插入图片描述
请注意,编译器会给出有关return语句的错误消息main():由于将的声明解释time_keeper为函数声明,因此我们将无法对此调用成员函数get_time()

强制编译器将其视为变量定义的常见方法是:

  • 要添加一对额外的括号:
    TimeKeeper time_keeper((Timer()));
  • 要使用副本初始化:
    TimeKeeper time_keeper = TimeKeeper(Timer());
  • (在C ++ 11和更高版本中。)对括号使用初始化列表初始化:
    TimeKeeper time_keeper{Timer()};
    TimeKeeper time_keeper(Timer{});
    TimeKeeper time_keeper{Timer{}};

Example with functions

当函数强制转换以 初始化变量 或 传递给构造函数参数 时,函数将产生Most vexing parse 。

void f(double adouble) {
  int i(int(adouble)); 	//旨在强制转换以初始化变量
}

在这种情况下,在double周围的括号是多余的,并且i的声明和一个等效于以下内容的函数声明相同

// 接受一个int并返回一个int的函数声明
int i(int adouble);

为了消除这一点,有利于变量声明,可以使用与上述第一种情况相同的技术。另一种解决方案是使用强制转换符号:

//声明一个名为“ i”的变量
int i((int) adouble);

或者也可以使用 named cast :

// declares a variable called 'i'
int i(static_cast<int>(adouble));

Uniform initialization syntax (统一初始化语法)

使用C ++ 11中引入的新的初始化列表可以解决此问题。 当使用花括号时,有问题的代码将是明确的:

 TimeKeeper time_keeper{Timer{}};

如上所述使用花括号为TimeKeeper类的变量time_keeper创建变量定义,并使用Timer类的匿名实例进行初始化。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值