轉(zhuǎn)自網(wǎng)絡(luò),來源不可考.
在這里,我想每天來更新一些關(guān)于CPP
的,我們應(yīng)該知道的知識,日積月累,我相信一定能夠到達一個比較高的境界的.雖然我以后不一定會使用這門語言.
CPP的前向聲明
兩個類相互包含引用的問題
在構(gòu)造自己的類時希坚,有可能會碰到兩個類之間的相互引用問題,例如:定義了類A
類B
陵且,A
中使用了B
定義的類型裁僧,B
中也使用了A
定義的類型:
class A
{
int i;
B b;
}
class B
{
int i;
A* a;
}
請注意上面的定義內(nèi)容,一般情況下是不能出現(xiàn)類A
慕购,類B
相互引用都定義對象聊疲,即如下的樣子:
class A
{
int i;
B b;
}
class B
{
int i;
A a;
}
在這種情況下,想想能夠有a.b.a.b.a.b.a.b.a.b…………
沪悲,很有點子子孫孫無窮盡之狀获洲,那么我的機器也無法承受。最主要的還是這種關(guān)系很難存在殿如,也很難管理贡珊。這種定義方式類同程式中的死循環(huán)。所以涉馁,一般來說门岔,兩者的定義,至少有一方是使用指針烤送,或兩者都使用指針寒随,但是決不能兩者都定義實體對象。
言歸正傳,那么妻往,在定義時因為相互引用肯定會需要相互包含頭文檔逢防,假如僅僅只是在各自的頭文檔中包含對方的頭文檔,是通但是編譯的蒲讯,如下:
//class A.h
#include "B.h"
class A
{
int i;
B b;
}
//class B.h
#include "A.h"
class B
{
int i;
A *a;
}
如上的包含方式可能會造成編譯器有錯誤提示:A.h
文檔中使用了示知類型B
。
怎么辦灰署?
一般的做法是:兩個類的頭文檔之中判帮,選一個包含另一個類的頭文檔,但另一個頭文檔中只能采用class *溉箕;
的申明形式晦墙,而在實現(xiàn)文檔中(*.cpp
)中包含頭文檔,如下:
//class A.h
#include "B.h"
class A
{
int i;
B b;
}
//class B.h
class A;
class B
{
int i;
A *a;
}
//B.cpp
//在B.cpp中的文檔包含處要有下面語句肴茄,否則不能調(diào)用成員a的任何內(nèi)容
#include "A.h"
B::B()
{
……
}
為什么要前向聲明?
我們先舉一個栗子:
//foo.h
class foo
{......};
//util.h
class foo;
class util
{
private:
foo* m_foo;
};
前向聲明用于降低
inclusion tree
的復(fù)雜程度晌畅,降低模塊間的耦合度。前提是前向聲明的類
foo
只能用來定義指針或者引用寡痰,而不可以定義實體對象抗楔,因為指針占用的空間大小固定,而類實體占用的空間大小必須引入頭文件才能確定拦坠。
前向聲明是一種不完全類型聲明连躏,所以它并不能取代完全類型,對于編譯器來說贞滨,在需要知其被聲明對象大小和內(nèi)容時入热,前向聲明,己不可用晓铆。故其應(yīng)用場景勺良,只有一下兩點:
- 聲明引用和指針;
- 作函數(shù)(僅聲明)的返回類型或是參數(shù)類型.
實現(xiàn)方式是在
util.h
頭文件中聲明類foo
,而不引入頭文件foo.h
骄噪。關(guān)于這點尚困,你可能會說,即使util.h
文件里不包含foo.h
链蕊,但是你util.cpp
文件中仍然要包含foo.h
尾组。的確。那么問題來了示弓,如果別人要使用你的util
類讳侨,就不需要知道foo
類的相關(guān)信息了。如果即使foo
發(fā)生改變奏属,引用util.h
的那文件跨跨,也不需要重新編譯了。如果你將foo
和util
封裝成庫,那只需要公開util.h
就可以了勇婴,foo.h
根本不需要露面忱嘹,也就加強了封裝性。否則耕渴,你發(fā)布的庫還必須帶著foo.h
一起發(fā)布拘悦。對于類和結(jié)構(gòu)體茬高,都可以用以上方式進行聲明媒峡,但是對于結(jié)構(gòu)體树瞭,有一種情況是無法前向聲明的:
typedef struct{ …… }MyStruct, *MyStruct;
對于這種形式呜笑,你是無法用MyStruct
進行前向聲明的由桌。所以盡量不要將結(jié)構(gòu)體設(shè)計成這種形式扯旷,哪怕非得這樣寫庙洼,也給它個名字赵讯,以便前向聲明:
cpp typedef struct _MyStruct{ …… }MyStruct, *MyStruct;
總結(jié)
所以這點的結(jié)論其實很簡單,那就是如果可以的話,盡量多使用cpp
的前向聲明,因為這個玩意可以減少依賴,如果很多文件包含了某個頭文件,如果這個頭文件發(fā)生改變,那么這些包含了頭文件的文件都要重新編譯,這是一件非常耗時的事情,這雖然是一個小的知識點,但是用處還是挺大的.