the most vexing parse

前几天群里遇到一个问题,后来经过在sof提问之后,才知道了这是C++一个"坑"。英文叫"the most vexing parse",翻译过来就是"最蛋疼的解析"。


"the most vexing parse" 实际上指的是C++语法上的一种二义性,举例来说,

class Timer
{
public:
    Timer();
};

class TimerKeeper
{
public:
    TimerKeeper(const Timer& t);

    int get_time();
};

int main(int argc, char *argv[])
{
    TimerKeeper time_keeper( (Timer()) );

    return time_keeper.get_time();
}


$ g++ -c test.cpp
test.cpp: In function ‘int main(int, char**)’:
test.cpp:21:24: error: request for member ‘get_time’ in ‘time_keeper’,
   which is of non-class type ‘TimerKeeper(Timer (*)())’

其实我们的本意是要用一个 Timer 的匿名对象来构造一个 TimerKeeper 的对象,但是编译器把那一行当成了一个函数声明,所以报的错为 time_keeper 不是一个类类型,而是一个返回值为 TimerKeeper,传入是一个返回值是=Timer=,没有输入参数的匿名参数。

一种解决办法是为参数外层加上一个括号,强制让编译器以为这是一个变量定义:

TimerKeeper time_keeper( (Timer()) );

C++11 为我们提供了统一的初始化方式(使用={}=),可以用来解决此类问题,如:

TimerKeepper time_keeper{ Timer{} };

以上大部分译自: Most vexing parse


其实在此之前曾经遇到过为什么不可以显示调用类的无参构造函数呢,比如 =ClassObj obj()=,以前搞明白了编译器把这一行代码认为是一个函数声明了。再次遇到类似的问题还是卡了很长时间。

感觉还是需要多总结记录,无论多小的知识点,有的时候卡在了视野的盲区,愣是找不到原因。

Date: 2013-12-04 00:00:00

Author: JerryZhang