为什么一个函数声明在另一个函数中可以编译,它是做什么的?

26

我本意是要调用一个私有类成员函数,但由于复制粘贴错误,把这个函数声明的代码行也粘贴进了头文件里:

void DebugView::on_cbYAxisEnabled_stateChanged(int)
{
    void updateAxisEnabled();
}

代替

void DebugView::on_cbYAxisEnabled_stateChanged(int)
{
    updateAxisEnabled();
}

令人惊讶的是,代码被编译并执行了。然而,方法updateAxisEnabled()没有被执行。

那么,为什么它能够编译通过呢?是在方法体内声明了一个局部函数还是void指示编译器忽略后面的内容?

编译器是Visual Studio 2008。

P.S.:我知道在函数内声明/定义类,但不知道在C++中是否可以声明嵌套函数。


4
现在你知道C++中函数内部定义/声明类是可以的,但函数内部定义/声明函数也是可以的。 - deviantfan
2
与任何前向声明一样,您这样做的原因是告诉编译器该符号的定义存在于其他地方。 - AndyG
@AndyG:好的,明白了!这个范围是全局的,所以实际上并没有什么魔法。 - Valentin H
我认为这是经典的“令人烦恼的解析”问题的变体。例如,请参见此处 - user786653
@user786653:我认为这些问题并不相关。你所指的问题是关于在C++中“()”不是表达式的问题。在这里,我不知道成员函数内部可以进行前向声明。很明显,C++中任何看起来像函数声明的东西都会被编译器视为函数。在你提到的问题中,A a(); 显然是一个函数声明,而不是类A的对象创建。 - Valentin H
显示剩余4条评论
2个回答

38

void updateAxisEnabled(); 是一个函数声明。

示例:

#include <cstdio>

void a();
void b();

int main(void) {
    a();
    b();
    return 0;
}

void a() {
    void c(); // Declaration
    c(); // Call it
}

void b() {
    c(); // Error: not declared
}

void c() {
    puts("Hello, world!");
}

太棒了!它可以工作。我在这里试过了:https://gcc.godbolt.org/。很高兴知道,在成员函数中可以进行前向声明。谢谢! - Valentin H

5

在函数范围内声明函数是完全允许的:函数可以在任何作用域中声明。

C++程序员常犯的一个错误是:

void foo()
{
    MyObject bar(); // 1
    bar.someMethod(); // 2
}

这段代码将会编译失败,因为第一行并没有声明一个名为barMyObject对象并显式调用它的构造函数;相反,它声明了一个名为bar函数,该函数返回一个MyObject对象。因此,实际上不存在可以调用someMethod方法的对象。


这就是为什么我喜欢使用这种语法来初始化我的变量:MyObject bar{}; - Justin
@Just 是的,自 C++11 起,统一初始化可以解决这个问题。 - edmz
请注意,您不能在类作用域中声明非成员函数,除非将其声明为友元。 - Brian Bi
@Brian:它的语法是什么? - Valentin H
@Brian 奇怪!甚至可以在类声明作用域内定义全局非成员函数。似乎又是另一个案例:http://mindprod.com/jgloss/unmain.html :-) - Valentin H
@Brian 对,成员函数是一个例外。 - edmz

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