在尝试理解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 (*)()
指定一个函数指针,因为我发现它更清楚。
答案 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{}};
并且没有解析歧义。