函数调用缺少参数列表警告

时间:2015-12-28 18:21:25

标签: c++ c++11

我正在阅读" C ++编程语言 - 第四版"我正在打一个简单的练习只是为了得到一些C ++语法,我不小心偶然发现了一些令我眉毛的东西。简而言之,我忘了在()添加accept in main:

bool accept()
{
    cout << "Do you want to proceed (y or n)?\n";

    char answer = 0;
    cin >> answer;

    if (answer == 'y')
    {
        return true;
    }
    return false;

}

int main()
{
    accept;
}

运行并编译并生成(在VS2015中)

  

C4551 - 函数调用缺少参数列表

我发现自己正在阅读lambdas和一些关于SO的问题应该被关闭,因为他们主要是要求调试我的代码。&#34;

我认为如果代码编译并运行,并且该函数包含一个阻塞语句(等待用户输入)和一个返回类型,那么所有代码​​都将按预期执行,而不管是否缺少括号;但事实并非如此。

此外,我想我会将主调用accept更改为bool a = accept; cout << a;以尝试阻止任何优化(如果那是实际发生的情况),并且没有调用{ {1}}代码。

我很想知道的是:

  1. accept()编译进来的调用是什么?
  2. 为什么accept中的代码被调用
  3. 为什么这只是一个警告,而不是错误(我知道我可以更改配置以将其显示为错误,我更多地质疑当实际结果与预期结果不同时默认情况下这是如何被接受的语法&#34;戏剧性地?&#34;这个问题可能是基于意见的,如果你同意的话就省略它。)
  4. 在main中运行accept代码会生成bool a = accept; cout << a;作为输出。当1是默认的bool值(至少在C#中)并且由于接受代码没有被执行而没有返回真值时,怎么会这样呢?

2 个答案:

答案 0 :(得分:13)

  1. 没有“致电accept”。见#3。

  2. 因为#1。

  3. 使用函数名而不使用函数调用语法(即:())意味着您正在访问函数本身。例如,您可以将其存储在函数指针中(通过函数到指针衰减):

    using my_func = bool(*)(); //Function that takes nothing and returns a bool.
    my_func var = accept; //Store a pointer to `accept`.
    

    然后,您可以发出var();,即accept

    但是,因为你从不存储函数,编译器猜测你可能想要调用函数,而不是访问函数的指针。 accept;但是是合法的C ++语句,因此编译器不能对其进行错误。它可以发出警告,因为语句没有任何结果,你可能打算调用该函数。这与1;这样的陈述没有什么不同:完全合法,但完全没用。

  4. 这是因为C ++技巧。非空指针衰减到布尔值true。并且accept衰减到非空的函数指针。因此,转换为bool时,它将为true。你还没有调用这个功能。

答案 1 :(得分:8)

在C ++中,任何以分号后跟的表达式都是合法的陈述。 (为什么?因为C让你这样做,我想)。这意味着以下所有内容都是法律声明:

 5;
 3 + 5;
 1 % 2 == 0;

此表单语句的效果是表达式被计算然后被丢弃。一个好的优化编译器会消除这里的所有逻辑,因为这些都没有任何副作用。

在你的情况下,写

accept;

是一个法律声明,因为accept是一个表达式,用于评估函数accept的引用。这意味着accept;作为语句意味着&#34;评估accept的地址,然后丢弃它。&#34;这里没有调用函数的原因是函数名本身并不调用函数;你需要括号(函数调用运算符)来实际调用。例如,如果要将函数传递给另一个函数,这很有用。例如,您可能希望将比较函数传递给std::sort,如下所示:

std::sort(range.begin(), range.end(), nameOfMyComparisonFunction)

在这里,如果尝试调用nameOfMyComparisonFunction,那将是一个真正的问题,因为在排序例程开始之前,参数不可知。

那为什么这是警告而不是错误?嗯,它是完全合法的C ++代码,因此编译器无法顺从地将其称为错误。但是,编译器将其标记为警告是正确的,因为它几乎肯定意味着您犯了错误。也就是说,大多数编译器都有一些设置会将警告报告为错误,如果你将警告级别提高到足够高,编译器可能说&#34;这是如此可疑,以至于我是假设你搞砸了什么。&#34;

关于你的最后一个 - 为什么

bool a = accept;

最终将a设置为true?在C ++中,任何非空指针都会隐式转换为true,任何空指针都会隐式转换为false。在C ++中,函数可以隐式转换为指向自身的指针,因此在这种情况下accept计算为accept函数的地址,该函数是非空的,因此它将a设置为{ {1}}。当你写下

true

该值打印为1,因为cout << a << endl; 值默认打印为1和0而不是booltrue。那就是说,你可以写

false

并且您会看到cout << boolalpha << a << endl; 打印出来。

希望这有帮助!