3

在试图理解 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 (*)()来指定函数指针,因为我发现它更清晰。

4

2 回答 2

8

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

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

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

然后程序员将被迫声明中写入参数名称

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 语法?

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

而且由于它们在其他情况下的行为不同,我们拥有它们,我们需要它们。该标准不(也不应该)禁止一种语法,因为它们作为参数类型的行为相同。

于 2012-07-18T06:46:21.053 回答
3

请注意...您已被听到:)

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

于 2012-07-18T07:49:15.603 回答