Zac*_*Saw 3 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 (*)());
}
Run Code Online (Sandbox Code Playgroud)
那么为什么不简单地禁止TimeKeeper time_keeper(Timer())成为一个函数声明,它接受一个未命名的函数ptr返回类型Timer?是TimeKeeper time_keeper(Timer (*)())劣等的函数声明者?
是不是由于这种语法,我们甚至得到这种模棱两可,或者我错过了什么?
编辑:就个人而言,我从来没有用过TimeKeeper time_keeper(Timer())函数声明.我总是用它Timer (*)()来指定一个函数指针,因为我发现它更清楚.
那么为什么不简单地禁止TimeKeeper time_keeper(Timer())是一个函数声明,它接受一个未命名的函数ptr返回类型Timer?
假设这个函数声明被拨号了一段时间,因为它使用了未命名的 参数.如果是这样,那么以下声明也将被禁止:
int max(int,int); //error (in hypothetical C++)
int min(int,int); //error (in hypothetical C++)
Run Code Online (Sandbox Code Playgroud)
而随后的程序员将被迫写的参数名称,在声明以及:
int max(int a,int b); //ok
int min(int a,int b); //ok
Run Code Online (Sandbox Code Playgroud)
但是其他人会站起来问:"为什么我不会在声明中使用它时强制在参数名称中写入参数名称?为什么它不是可选的? "
我认为这个人是理性的,他提出的要点是有道理的.强制程序员在声明中命名参数确实是不合理的.
-
阅读您的评论,您似乎认为以下声明完全相同:
int max(Timer());
int max(Timer(*)());
Run Code Online (Sandbox Code Playgroud)
号他们不是恰好从同一个语法的角度来看,虽然都是在严格相同的行为的观点.
微妙的区别在于,在前者中,参数类型是一个不带任何东西并且返回的函数Timer,而在后者中,参数类型是指向不带任何东西的函数的指针,并返回Timer.你看得到差别吗?
但问题是,为什么他们的行为方式相同?答案是,在前一个声明中,参数类型被调整,然后变成指针类型,因此它的行为与第二个声明相同.
C++ 03标准在§13.1/ 3中说,
仅在那一个中不同的参数声明是函数类型 而另一个是指向相同函数类型的指针是等效的. 也就是说,调整函数类型以成为函数类型的指针(8.3.5).
我希望它在C++ 11中也是一样的.
-
你的疑问(取自评论):
仍然没有更接近理解为什么我们需要2语法?
因为它们是两种不同的类型.函数类型和指向函数类型的指针.仅作为参数类型,它们的行为相同.否则,他们就不同了.在这里查看我的答案,看看他们的行为有何不同:
而且由于它们在其他情况下表现不同,我们有它们,我们需要它们.标准不会(也不应该)禁止一种语法,因为作为参数类型它们的行为相同.