理解'最令人烦恼的解析' - 为什么允许含糊不清的语法?

时间:2012-07-18 06:22:27

标签: c++ most-vexing-parse

在尝试理解C / C ++中的“最令人烦恼的解析”问题时,会立即想到这个问题 - 为什么会出现导致此问题的语法?

例如,

class Timer
{
public:
    Timer();
};

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

    int get_time()
    {
        return 1;
    }
};

int main()
{
    TimeKeeper time_keeper(Timer());
    // the above is eq to this: TimeKeeper time_keeper(Timer (*)());
}

那么为什么不简单地禁止TimeKeeper time_keeper(Timer())成为一个函数声明,它接受一个未命名的函数ptr返回类型Timer? TimeKeeper time_keeper(Timer (*)())是否低于函数声明符?

是不是由于这种语法,我们甚至得到了这种模糊性,或者我错过了什么?

编辑:就个人而言,我从未使用TimeKeeper time_keeper(Timer())作为函数声明。我总是使用Timer (*)()指定一个函数指针,因为我发现它更清楚。

2 个答案:

答案 0 :(得分:8)

  

那么为什么不简单地禁止TimeKeeper time_keeper(Timer())成为一个函数声明,它接受一个未命名的函数ptr返回类型Timer?

假设这个函数声明被拨号一段时间,因为它使用了未命名的参数。如果是这样,那么以下声明也将被禁止:

int max(int,int);  //error (in hypothetical C++)
int min(int,int);  //error (in hypothetical C++)

然后程序员将强制在声明中编写参数 name

int max(int a,int b);  //ok 
int min(int a,int b);  //ok 

但是其他人会站起来问:“为什么我不能在声明中使用它时强制写入参数名称?为什么它不是可选的?

我认为这个人是理性的,他提出的要点是有道理的。 强制程序员在声明中命名参数确实是不合理的。

-

阅读您的评论,您似乎认为以下声明完全相同:

int max(Timer());
int max(Timer(*)());

没有。从语法的角度来看,它们完全相同,但它们与行为的观点完全相同。

微妙的区别在于,在前者中,参数类型是一个不带任何东西的函数,并返回Timer,而在后者中,参数类型是指针到函数不带任何东西,并返回Timer。你看到了区别吗?

但问题是,为什么他们的行为方式相同?答案是,在前一个声明中,参数类型是调整,然后变为一个指针类型,因此它的行为与第二个声明相同。

C ++ 03标准在§13.1/ 3中说明,

  

仅与那个不同的参数声明是函数类型   另一个是指向同一函数类型的指针是等价的。   即,调整函数类型以成为函数的指针   输入(8.3.5)。

我希望它在C ++ 11中也是一样的。

-

您的疑问(摘自评论):

  

仍然没有更接近理解为什么我们需要2语法?

因为它们是两种不同的类型。函数类型和指向函数类型的指针。仅作为参数类型,它们的行为相同。否则,他们就不同了。请在此处查看我的答案,了解他们的行为方式:

由于它们在其他情况下表现不同,我们 它们,我们需要它们。标准不会(也不应该)禁止一种语法,因为它们的行为类型相同。

答案 1 :(得分:3)

请注意......你听说过:)

C ++ 11通过引入统一初始化语法专门解决了这个问题。现在你可以写TimeKeeper time_keeper{Timer{}};并且没有解析歧义。