返回函数类型的前向声明

Han*_*lil 6 c++ forward-declaration

正如这个答案所暗示的那样,我知道允许在函数声明中使用不完整类型作为返回值.所以我写了下面的代码:

Obj.h

class Obj {
    int x;
};
Run Code Online (Sandbox Code Playgroud)

FH

class Obj;
Obj f();
Run Code Online (Sandbox Code Playgroud)

f.cpp

#include "Obj.h"

Obj f() {
    return Obj();
}
Run Code Online (Sandbox Code Playgroud)

main.cpp中

#include "f.h"
int main() {
    f();
    return 0;
};
Run Code Online (Sandbox Code Playgroud)

使用以下编译器编译此代码:

g++ (GCC) 4.8.5 20150623 (Red Hat 4.8.5-4)

使用以下编译命令:

g++ *.cpp
Run Code Online (Sandbox Code Playgroud)

给出以下错误:

main.cpp: In function 'int main()':
main.cpp:4:7: error: invalid use of incomplete type 'class Obj'
     f();
       ^
f.h:1:7: error: forward declaration of 'class Obj'
 class Obj;
       ^
Run Code Online (Sandbox Code Playgroud)

因此编译器不允许在函数声明中使用不完整类型作为返回值.解释是什么?

AnT*_*AnT 9

正如你自己所说的那样"允许在函数声明中使用不完整类型作为返回值".这正是编译器允许你做的事情.您在非定义功能成功地使用一个不完整的返回类型声明 -你的声明ff.h编译没有任何问题.

但这就是你被允许做的一切.这绝不会改变以下事实:

  1. 在功能定义时,返回类型应完整
  2. 在函数调用时,返回类型应完成.

在您的代码中,main()您尝试调用以不完整返回类型声明的函数.因此错误.

5.2.2函数调用[expr.call]

10如果结果类型是左值引用类型或对函数类型的右值引用,则函数调用是左值;如果结果类型是对象类型的右值引用,则为xvalue,否则为prvalue.

11如果函数调用是对象类型的prvalue:

- 如果函数调用是 - decltype-specifier的操作数或 - 作为decltype-specifier的操作数的逗号运算符的右操作数,则不为prvalue引入临时对象.prvalue的类型可能不完整.[...]

- 否则,prvalue的类型应完整.

换句话说,你被允许的是用不完整的返回类型引入你的函数的早期前向声明.但是当你定义该函数或调用它时,你应该完成返回类型.


Pet*_*ker 1

正如您所看到的,并非所有不完整的类型都是允许的。事实上,规则是函数可以返回不完整类型的指针或引用。原因是在调用时,编译器必须能够生成代码来处理返回的对象。当没有有关对象内容的信息时,编译器无法生成代码。例如,假设Obj有一个不平凡的析构函数;如果编译器不知道这一点,它就无法生成代码来销毁该对象。当返回类型是指针或引用时,编译器拥有所需的所有信息:指针和引用通常不依赖于目标对象的详细信息。