2010-09-29 60 views
6

我一直在閱讀一些關於遠期聲明,包括在這個論壇。他們都說,這讓我們可以包含頭文件,但下面的代碼生成錯誤:正向聲明產生不兼容的類型錯誤

#ifndef CLASSA_H_ 
#define CLASSA_H_ 

class B; 

class A { 

public: 
    A(); 
    ~A(); 
    int getCount(); 
private: 
    static int _count; 
    int _num; 
    B _b1; //ERROR 

}; 

編譯器說: A.h:23: error: field ‘_b1’ has incomplete type

我注意到,如果我做B*類型的_b1問題解決了。

那麼前向聲明只適用於指針類型嗎?
如果我想A持有B對象我必須#inlcude "B.h"

謝謝!

+0

有點自我推銷:這是一個答案,解釋[你可以做什麼,不能用不完整的類型](http://stackoverflow.com/questions/553682/when-to- use-forward-declaration/553869#553869)(ie已聲明但尚未定義的類型)。 – 2010-09-29 17:02:02

回答

10

編譯器必須知道類B的確切定義,以確定至少給類A的大小。如果你使用一個指針,它知道它的大小。

請注意,循環依賴不可能。如果你想

class A { B b; }; 
class B { A a; }; 

然後A和B必須具有無限的大小...

+0

+1我很驚訝,我不知道 – 2010-09-29 16:12:54

0

是的,你就必須

#include "B.h" 

,如果你想在你的類A,B

0

是,前置聲明如果你使用指針和引用正向聲明的類型只工作。如果按值使用對象,則需要包含完整的頭文件。

+0

那麼,前向聲明可以用作函數_declarations_中的一個類型:'B f(B);'然而,您需要'B'的完整定義來實際_define_這個函數。 – sbi 2010-09-29 16:17:26

6

可以使用正向聲明的類型

  1. 使用指針和引用它作爲數據成員
  2. 將它用作函數的參數(即使每次複製)或返回類型(甚至每個副本返回)聲明離子

您需要一種的完整定義,以便

  1. 使用它作爲類的數據成員
  2. 在函數中使用它定義

如果你還記得,一個向前聲明實際上是一個misnomed 聲明there is no other way of declaring a class type,所以類類型的任何聲明是一個向前聲明),而且,每當你class後打開括號/ struct/union加上標識,你是定義一類,你需要記住的是,你:

  • 需要一個完整的定義中使用的類型本身的定義
  • 只有一個聲明就完事使用類型本身在聲明
  • 只有一個聲明脫身時,你只用指針和引用,也不要試圖訪問成員或嵌套類型(任何與.->,和::前面)