庫是一組代碼模塊,它按照可復用的方式組織而成。代碼庫中保存的是有用、可復用的、編譯后的代碼,這樣,程序員不需要處理代碼庫的任何源代碼都能夠利用它的功能。 當復用來自庫中的任何模塊時,其工作由鏈接器在鏈接編譯階段完成,即在編譯之后的程序代碼和標準庫中的庫二進制文件進行鏈接,在程序中調用庫函數時將直接跳到庫中對應的代碼并執行。 庫是一個文件,它包含了一個或者多個編譯后的文件(稱為目標文件),并對其進行索引,以便鏈接器能夠更容易地找到對應符號(例如:類名稱、類成員、函數、變量等)以及它們的定義。
如果項目工程依賴于某個外部庫,則必須編輯這個工程文件,指定庫的位置和名稱并將它的值賦予 INCLUDEPATH 和 LIBS 。
如果一個程序元素復用了另外一個程序元素,則它們之間就存在依賴性。也就是說,構建、使用或者測試這個元素時,就要保證另一個元素存在且是正確的。 如果編譯 PRogElement2.cpp 時必須包含 ProgElement1.h ,則稱這種依賴性為編譯時依賴;如果目標文件 ProgElement2.o 包含 ProgElement1.o 中定義的符號,則稱其為鏈接時依賴。 代碼復用,這是一個有價值且重要的目標,但總會產生依賴。當設計類和庫時,需要確保盡可能地減少不必要的或者無意的依賴性,因為它們會延長編譯時間,降低類和庫的可復用性。每一次用 #include 指令包含頭文件時,都會帶入這個頭文件中所包含的其他頭文件,這樣它們之間的依賴性就會相應的增多。
框架是一個(通常非常大)通用(或針對特定領域的)類與約定的集合,其目的是提高設計的一致性??蚣芙洺1挥脕韯摻▓D形化應用、數據庫應用或者其它復雜的軟件。如同底層驅動中的機制和策略。 框架一般都具有文檔豐富的公共 API 。API 是庫中公共函數、類和接口的描述。為了實現框架,可以采用設計模式。 Qt 是許多開源的面向對象框架中的一種,它提供一組可復用的組件(即每個平臺下都有特定的工具集調用),用于創建跨平臺的應用。而利用 Qt 這樣的多平臺框架,就可以從其他人的創造性工作中獲得大量的好處。
比如:
序列化器是一種只負責讀取或寫入對象的對象模板。 QTextStream 序列化器用于讀寫人類可以直觀理解的文本文件。而 QDataStream 序列化器用于讀寫結構化的二進制數據。(比如說:可以將一個結構體完整的寫入到文件,且輕易讀出),也用于網絡數據的傳輸。 下面一個實例展現了 QTextStream 和 QDataStream 的方面,即顯示了序列化器模式在處理對象存儲時的優勢。
//MeataDataValue 代表的而是一首歌曲的屬性class MetaDataValue {public: friend QTextStream& Operator<< (QTextStream& os, const MetaDataValue& mdv); friend QTextStream& operator>> (QTextStream& is, const MetaDataValue& mdv); friend QDataStream& operator<< (QDataStream& os, const MetaDataValue& mdv); friend QDataStream& operator>> (QDataStream& is, const MetaDataValue& mdv); friend bool operator== (const MetaDataValue&, const MetaDataValue&); virtual QString fileName()const; virtual QString genre()const; virtual QString artist()const; virtual QString trackTitle()const; virtual QString trackNumber()const;protected: bool m_isNull; QUrl m_Url; QString m_TrackNumber; QString m_TractTitle; QString m_Comment; QString m_Genrs; QString m_Artist; QTime m_TrackTime; QString m_AlbumTitle; QImage m_Image;};using namespace std;//寫入(插入)數據到流中QTextStream& operator<< (QTextStream& os, const MetaDataValue& mdv){ QStringList sl; s. << mdv.m_Url.toString() << mdv.trackTitle() << mdv.artist() ; os << sl.join("/t") << "/n";//以自定義的格式,插入數據到流中 return os;}//序列化器,使用一個序列化流,流中可以保持各式各樣的類型,int,QString,QTime 。。。//重寫插入運算符和提取運算符。來操作一條流,效率,代碼整潔度遠高于操作對象中的單個數據。//從流中讀取(提?。祿TextStream& operator>> (QTextStream& is, MetaDataValue& mdv) { QString line = is.readLine(); QStringList fields = line.split("/t");//以自定義的格式提取數據 while (fields.size() < 9) { //如果長度小于9則用填充的方式來避免 非法 的內存操作。 fields << ""; } mdv.m_isNull = false; mdv.m_Url.setUrl(QUrl::fromUserInput(fields[0])); //從流中取出數據,然后定向到內存變量中 ; ; ; //代表省略。。。內容為:一系列成員變量的賦值。 return is;//此次只讀了一行數據}QDataStream& operator<< (QDataStream& os, const MetaDataValue& mdv) { os << mdv.m_Url << mdv.trackTitle() << mdv.m_Image; ;;;; //此次,提取數據,DataStream和TextStream的區別也在于此,DataStream存的是二進制流,故流中可以是int,QTime,QStringStream等不同類型的數據。而TextStream中只能存的是字符串,QString return os;}QDataStream& operator>> (QDataStream& is, MetaDataValue& mdv) { is >> mdv.m_Url >> mdv.m_TrackTime >> mdv.m_Artist >> mdv.m_AlbumTitle;;;; //由于二進制流的特殊之處,成員變量直接對號入座。 return is;}當然除了以上好的設計模式外,還有一些沒有效果,低效率的編程實踐被稱為反模式 例如:
軟件設計反模式 接口膨脹: 接口的功能強大而復雜,以至于難于復用面對對象設計反模式 循環依賴:在對象或者軟件模塊之間引入了不必要的直接或間接的依賴“上帝”對象:指擁有太多屬性或太多責任的對象。比如:將模型和視圖的代碼組合在同一個類中編程反模式 魔幻數據:算法中包含了未解釋的數字魔幻字符串:代碼中包含直接的字符串作為事件類型進行比較方法學反模式 復制——粘貼編程:復制并修改已有的代碼,而不是創建更通用的解決方案一切從頭開始:不采用已有的解決方案,而是采用(執行起來表現要差很多)定制的解決方案新聞熱點
疑難解答