2016-11-10 76 views
2

由於answer暗示,我知道允許在函數聲明中使用不完整的類型作爲返回值。所以我寫了下面的代碼:函數返回類型的前向聲明

Obj.h

class Obj { 
    int x; 
}; 

f.h

class Obj; 
Obj f(); 

f.cpp

#include "Obj.h" 

Obj f() { 
    return Obj(); 
} 

使用以下編譯命令

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

的main.cpp

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

編譯此代碼與以下編譯器

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

因此,編譯器不允許在函數聲明中使用不完整類型作爲返回值。什麼解釋?

+1

您是否將f.cpp和main.cpp編譯在一起? – NathanOliver

+0

@NathanOliver我編輯了編譯命令。是的,我將它們編譯在一起 –

回答

1

正如您所見,並非所有不完整的類型都是允許的。實際上,規則是函數可以返回一個指針或引用爲不完整的類型。原因在於,在調用的時候,編譯器必須能夠生成代碼來處理返回的對象。當沒有關於對象內容的信息時,編譯器不能生成代碼。例如,假設Obj有一個非平凡的析構函數;如果編譯器不知道,它不能生成代碼來銷燬該對象。當返回類型是一個指針或引用時,編譯器擁有它需要的所有信息:指針和引用通常不依賴於目標對象的細節。

2

的這裏的問題是,main.cpp不知道什麼Obj是那麼當它編譯main.cpp它不能調用f,因爲返回類型是不完整的。您需要做的是將Obj的定義引入main.cpp。您可以在main.cpp中使用#include "obj.h"來完成此操作。

Live example

+0

我知道包括Obj.h將解決問題。但問題是關於函數返回類型的前向聲明。我在我的問題中提到的參考文獻指出,可以這樣做。 –

+2

@HannaKhalil可以這麼做。當你使用這個函數的時候會出現這個問題。當你使用它時,需要定義返回類型。 – NathanOliver

5

正如你說,它自己「這是允許使用不完全類型作爲函數的聲明返回值」。這正是編譯器允許你做的。您在非定義函數聲明中成功使用了不完整的返回類型 - f的聲明在f.h編譯時沒有任何問題。

但這就是你所允許的。這不以任何方式改變的事實是:

  1. 在功能定義點的返回類型必須完整
  2. 在功能調用點的返回類型應完整。

在您的代碼中,在main()裏面,您嘗試調用一個用不完全返回類型聲明的函數。因此錯誤。

5.2.2 Function call [expr.call]

10 A function call is an lvalue if the result type is an lvalue reference type or an rvalue reference to function type, an xvalue if the result type is an rvalue reference to object type, and a prvalue otherwise.

11 If a function call is a prvalue of object type:

— if the function call is either — the operand of a decltype-specifier or — the right operand of a comma operator that is the operand of a decltype-specifier, a temporary object is not introduced for the prvalue. The type of the prvalue may be incomplete. [...]

— otherwise, the type of the prvalue shall be complete.

換句話說,你被允許的是用不完整的返回類型引入你的函數的提前聲明。但是當你到達定義該函數或調用它,你應該有返回類型完成。