国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > C++ > 正文

C++文件的依賴關系

2020-02-24 14:35:28
字體:
來源:轉載
供稿:網友

如果你正要學習或者對于C++比較上心的朋友可以看看此文,或許能給你意想不到的收獲喔,那閑話不多說了,一起來了解下C++文件的依賴關系。

首先我不給出依存關系的定義,我給出一個例子。


?class Peopel{
?public:
???? People(const std::string & name,const Date& brithday,Image Img)
???? std::string name( ) const;
???? Date birthDate( ) const;
???? Image img( ) const;
???? ...
?private:
???? std::string theName;?????????????? //名字
???? Date theBirthDate;???????????????? //生日
???? Image img;???????????????????????? //圖片
?};


如果編譯器沒有知道類string,Date和Image的定義,class People是無法通過編譯的。一般該定義式是由#include包含的頭文件所提供的,所以一般People上面有這些預處理命令

?

?


? #include
? #include "date.h"
? #inblude "image.h"
?class Peopel{
?public:
???? People(const std::string & name,const Date& brithday,Image Img)
???? std::string name( ) const;
???? Date birthDate( ) const;
???? Image img( ) const;
???? ...
?private:
???? std::string theName;?????????????? //名字
???? Date theBirthDate;???????????????? //生日
???? Image img;???????????????????????? //圖片
?};


那么這樣People定義文件與該三個文件之間就形成了一種編譯依存關系。如果這些頭文件任何一個文件被改變,或這些頭文件所依賴其他頭文件任何改變,那么每一個包含People類的文件就需要重新編譯,使用People類文件也需要重新編譯。想想如果一個項目包含一個上千的文件,每個文件包含其他幾個文件,依次這樣下來,改動一個文件內容,那么就需要幾乎重新編譯整個項目了,這可以說很槽糕了。

?

我們可以進行如下改動


?namespace std {
???? class string;
?}
?class Date;
?class Image;

?class Peopel{
?public:
???? People(const std::string & name,const Date& brithday,Image& Img)
??? std::string name( ) const;
??? Date birthDate( ) const;
??? Image img( ) const;
??? ...
private:
??? std::string theName;??????????????? //名字
??? Date theBirthDate;???????????????? //生日
??? Image img;???????????????????????? //圖片
};


這樣只有People該接口被改變時才會重新編譯,但是這樣有連個問題,第一點string不是class,它是個typedef basic_string string。因此上述前置聲明不正確(附其在stl完全代碼);,正確的前置聲明比較復雜。其實對于標準庫部分,我們僅僅通過#include預處理命令包括進來就可以了。

?

?


?#ifndef __STRING__
?#define __STRING__

?#include

?extern "C++" {
?typedef basic_string string;
?// typedef basic_string wstring;
?} // extern "C++"

?

#endif


前置聲明還有一個問題,就是編譯器必須在編譯期間知道對象的大小,以便分配空間。
例如:

?

?


? int main(int argv,char * argc[ ])
??? {
??????? int x;
??????? People p( 參數 );
??????? ...
??? }


當編譯器看到x的定義式,它知道必須分配多少內存,但是看到p定義式就無法知道了。但是如果設置為指針的話,就清楚了,因為指針本身大小編譯器是知道的。

?

?


#include
#include

?

class PeopleImpl;
class Date;
class Image;
class People{
public:
?? People(const std::string & name, const Date& brithday, const Image &Img);
?? std::string name( ) const;
?? Date birthDate( ) const;
?? Imge img( ) const;
?? ...
private:
?? PeopleImpl * pImpl;
}


PeopleImpl包含下面這三個數據,而People的成員變量指針指向這個PeopleImpl,那么現在編譯器通過People定義就知道了其分配空間的大小了,一個指針的大小。

?

?


?public PeopleImpl
?{
???? public:
???????? PeopleImple(...)
???????? ...
???? private:
???????? std::string theName;??????????????? //名字
???????? Date theBirthDate;???????????????? //生日
???????? Image img;???????????????????????? //圖片


這樣,People就完全與Date、Imge以及People的實現分離了上面那些類任何修改都不需要重新編譯People文件了。另外這樣寫加強了封裝。這樣也就降低了文件的依存關系。
這里總結下降低依存性方法:

?

?

?

1.如果可以類聲明就不要使用類定義了。
2.將數據通過一個指向該數據的指針表示。
3.為聲明式和定義式提供不同的頭文件。
  這兩個文件必須保持一致性,如果有個聲明式被改變了,兩個文件都得改變。因此一般會有一個#include一個聲明文件而不是前置聲明若干函數。
  像People這樣定?
?


?#include "People.h"
?#include "PeopleImpl.h"

?People::People(const std::string& name, const Date& brithday, const Image& Img)
?:pImpl(new PersonImpl(name,brithday,addr))
?{ }
?std::string People::name( ) const
?{
???? return pImpl->name( );
?}


而另外一種Handle類寫法是令People成為一種特殊的abstract base class稱為Interface類。看到interface這個關鍵字或許熟悉C#、java的同學可能已經恍然大悟了。這種接口它不帶成員變量,也沒有構造函數,只有一個virtual析構函數,以及一組純虛函數,用來表示整個接口。針對People而寫的interface class看起來是這樣的。

?

?


?class People{
?public:
???? virtual ~People( );
???? virtual std::string name( ) const = 0;
???? virtual Date brithDate( ) const =0;
???? virtual Image address( ) const =0;
???? ...
?};


怎么創建對象呢?它們通常調用一個特殊函數。這樣的函數通常稱為工廠函數或者虛構造函數。它們返回指針指向動態分配所得對象,而該對象支持interface類的接口。

?

?


?? class People {
???? public:
???????? ...
???????? static People* create(const std::string& name,const Date& brithday, const Image& Img);
???? };


支持interface類接口的那個類必須定義出來,而且真正的構造函數必須被調用

?

?


?class RealPeople:public People{
?public:
???? RealPeople(const std::string& name,const Date& birthday,const Image& Img)
???? :theName(name),theBrithDate(brithday),theImg(Img)
?{}
???? virtual ~RealPeople() { }
???? std::string name( ) const;
???? Date birthDate( ) const;
???? Image img( ) const;
?private:
???? std::string theName;
???? Date theBirthDate;
???? Image theImg;
?}


有了RealPeople類,我們People::create可以這樣寫

?

?


?People* People::create(const std::string& name, const Date& birthday, const Image& Img)
?{
???? return static_cast(new RealPerson(name,birthday,Img));
?}


Handle類與interface類解除了接口和實現之間的耦合關系,從而降低了文件間的編譯依存性。但同時也損耗了一些性能與空間。

以上就是C++文件的依賴關系的介紹,如果大家想了解更多相關內容,請持續關注本站,本站小編將在第一時間為大家帶來更好的經典內容。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 景德镇市| 阿城市| 滨州市| 文水县| 闽清县| 天台县| 康乐县| 襄城县| 安新县| 武冈市| 砀山县| 漳浦县| 绥棱县| 邢台县| 灵台县| 六枝特区| 曲阜市| 瑞昌市| 偃师市| 襄城县| 梁河县| 陵水| 尤溪县| 盐亭县| 古蔺县| 大理市| 葵青区| 和静县| 若尔盖县| 石渠县| 玛曲县| 乐平市| 灵台县| 白城市| 和政县| 临江市| 凤翔县| 白银市| 遵义市| 大冶市| 红河县|