C++函数调用前加void关键字,例如`main() {void func();}`。

4
void func() {assert(0);}
int main () {void func();}

上述代码没有调用func(),或者至少没有达到断言。虽然我不是非常需要知道,但我只是好奇,这里发生了什么?
4个回答

10

你正在声明一个名为func的函数原型,该函数不返回任何值且不接受参数。这是函数调用和函数原型之间微妙差别之一。请注意,在main上面的那行代码:void func() {assert(0);},它对于这是原型还是调用没有影响。你可以删除它,代码仍然会执行相同的操作——也就是什么都不做。

这也告诉你可以重新声明函数原型。甚至可以这样:

int main() {
    void blah();
    void blah();
    void blah();
    void blah();
}

而且代码仍然会像以前一样——什么都不做。

如果省略void,它将调用该函数。

此外,请注意,对于带参数的函数,以下内容:

int main() { func(4); }

如果你在函数前面加上void,像这样:

它就不会转变成原型。

int main() { void func(4); }

它只会产生一个语法错误。


5

正如其他人指出的那样,这行代码

void func();

在C和C++中,main内部被视为函数原型而不是对函数func的调用。如果愿意,您可以在函数内部声明函数原型,但实际上很少这样做。

事实上,这种写法是合法的,但会给程序员带来各种问题。例如,如果您将代码重新编写为

(void) func();

那么这将编译为对func的调用,其返回类型被显式地转换为void,以表示“我不关心这个返回值”。换句话说,这组括号将声明变成了语句。
在C++中,这个问题可能会加剧,因为下面的代码是一个函数原型,而不是调用默认构造函数的变量声明:
Object myObject();

虽然
Object myObject(137);

创建对象并将137传递到其构造函数中。
Object myObject;

创建对象而不调用构造函数。

在尝试声明一个对象并调用它的构造函数时,语言存在一个令人不安的边缘情况,称为“最恼人的解析”。例如,下面的代码是合法的C++代码,但它是一个函数声明而不是变量声明:

set<int> mySet(istream_iterator<int>(cin), istream_iterator<int>());

问题在于,这可能被解析为一个函数声明,而不是创建一个接受两个临时istream_iterator<int>作为参数的对象。为了解决这个问题,在C++中你需要写成:
set<int> mySet(istream_iterator<int>(cin), (istream_iterator<int>()));

如上所述,额外的括号可以将语句从函数原型强制区分为声明。

希望这有帮助!


4

即使不必要,您也可以声明函数。这就是您所做的,重新声明了该函数。


0
你正在 main() 函数内声明一个本地函数 void func()void 语句告诉编译器这是一个声明而不是函数调用。因此,去掉 void,你的函数就会被调用。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接