返回函数类型的前向声明

时间:2016-11-10 17:38:28

标签: c++ forward-declaration

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

Obj.h

class Obj {
    int x;
};

f.h

class Obj;
Obj f();

f.cpp

#include "Obj.h"

Obj f() {
    return Obj();
}

的main.cpp

#include "f.h"
int main() {
    f();
    return 0;
};

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

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

使用以下编译命令:

g++ *.cpp

给出以下错误:

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;
       ^

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

3 个答案:

答案 0 :(得分:8)

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

但是你可以这么做。这绝不会改变以下事实:

  1. 在功能定义时,返回类型应完整
  2. 在功能调用时,返回类型应完整。
  3. 在您的代码中,main()内部尝试调用以不完整返回类型声明的函数。因此错误。

      

    5.2.2函数调用[expr.call]

         

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

         

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

         

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

         

    - 否则,prvalue的类型应为   完整。

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

答案 1 :(得分:2)

这里的问题是main.cpp不知道Obj是什么,所以当它编译main.cpp时,由于返回类型,它无法调用f不完整。您需要做的是将Obj的定义引入main.cpp。您可以使用#include "obj.h"中的main.cpp执行此操作。

Live example

答案 2 :(得分:1)

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