標籤:

C++類和其友元類的頭文件該怎樣相互包含?

用vs2012編譯

原類:A。

B類中存在A類型的成員變數,同時B類中有個成員函數是A類的友元。A類和B類是分別定義在兩個頭文件中的。到底怎麼包含,快瘋了T_T。改來改去報的錯還不一樣,麻煩各位解答一下。

/*********************************A.h****************************/
#pragma once
//在A.h中還需要添加#include "B.h"和class B;嗎
class A
{
friend B::bfun();
public:
int a;
...
};
/*********************************B.h****************************/
#pragma once
#include "A.h"
//在B.h中還需要添加class A;嗎?
class B
{
public:

A a;

void bfun(){...}

};

/*********************************main.h*************************/
#include "A.h"
#include "B.h"
int main()
{
...

}


A.h==========================

class B;

class A{friend class B;};

B.h==========================

class A;

class B{friend class A;};

A.cpp========================

#include "A.h"

#include "B.h"

B.cpp========================

#include "A.h"

#include "B.h"

main.cpp========================

#include "A.h"

#include "B.h"


早年我在開發時也遇到過與題主所述類似的問題,在仔細思考了以後解決了,關鍵就在於盡量消除循環引用

1、如果是設計不合理,不該引用的出現了引用,那麼就應該取消掉這個引用。很多時候,你可能會為了編碼時調用方便,很隨意的增加了類之間的引用關係,那麼改掉這個毛病,必須是想明白了每個類的職責以及類和類之間的關係後再決定誰應該引用誰。

2、如果兩者之間必須互相引用,那麼考慮是不是可以抽象出第三個類,使得兩者不直接引用,而都通過第三者發生作用。

3、如果兩者之間必須互相引用,而且無法抽象出第三者過渡,那麼一定會有一方對另一方的引用僅是類型的引用,而不需該類中的成員,那麼向前聲明(forward declaration)對方即可(輪子哥的答案)。注意,這裡說的是在頭文件中。在實現文件中,通常都會引用到該類的成員。

4、如果你的兩個類的方法實現都希望是內聯的,而且又互相引用對方,那說明這兩個類是關係太密切了,而能用內聯又說明方法都很簡單,那乾脆兩個類都寫在同一個頭文件內吧。在整個文件的開始,加上對兩個類的向前聲明。


聲明的時候不用包含所聲明類的頭文件,所以友元聲明直接聲明就好了,否則會出現互相包含,造成很大的麻煩。

#include只是把多個文件複製在一起,所以只需要一個聲明,他們最終還是會遇到的。


其實你搞清楚編譯和鏈接的作用就明白了,編譯只需要聲明一下變數和函數就行,鏈接的時候才去找它的定義。

頭文件聲明和cpp文件里聲明並沒有什麼區別,#include 的作用只是把頭文件的代碼複製到當時文件而已。


看到這個問題,說一下我的理解. 聲明友元的那個類我們稱為A,由於它需要搜索另一個類B的函數名形參等等信息,因此單純的聲明class是不行的,需要寫上#include. 而另一個實現友元函數的類B,由於它不需要知道類A的其他信息,只需要用到引用或者指針,所以簡單的 class A聲明一下就可以了.

注意,不能多寫#include,多寫就出錯了!因為循環包含的問題,會導致編譯器執行到友元類成員聲明的時候,還沒有運行到友元聲明的那一步,所以會報unknown的錯誤.


B 包含 A,A 聲明 B。


論聲明的作用,在A.h裡面添加class B的聲明


推薦閱讀:

什麼時候用異常,什麼時候用斷言?
如何用 C++ 在 10 行內寫出八皇后?
C++20 有哪些值得注意的新特性?
string和char數組的區別是什麼以及map可否設置key為char數組?

TAG:C |