<big id="n3dbt"><strong id="n3dbt"></strong></big>
      1. <small id="n3dbt"><delect id="n3dbt"></delect></small>

        <thead id="n3dbt"><ruby id="n3dbt"><rp id="n3dbt"></rp></ruby></thead>
        <th id="n3dbt"></th>
        <span id="n3dbt"></span><span id="n3dbt"></span><span id="n3dbt"></span><strike id="n3dbt"></strike>

        建站百科Website News

        當前位置:首頁 »Git基礎:基本的Git概念

        Git基礎:基本的Git概念

        至成科技 2015-03-31 訪問量(1104) 評論(0)
        摘要:
        c++ 的代碼包含頭文件和實現文件兩部分, 頭文件一般是提供給別人(也叫客戶)使用的, 但是一旦頭文件發生改變,不管多小的變化,所有引用他的文件就必須重新編譯,編譯就要花時間,假如你做的工程比較大(比如二次封裝chrome這類的開發),重新編譯快速的時間就會浪費上班的大部分時間,這樣干了一天挺累的, 但是你的老板說你沒有產出,結果你被fired, 是不是很怨啊, 如果你早點看到這段文章,你就會比你的同事開發效率高那么一些,那樣被fired就不會是你了,你說這篇文章是不是價值千金!開個玩笑 :)
        言歸正傳,怎樣介紹編譯時間呢, 我知道的就3個辦法:
        刪除不必要的#include,替代辦法 使用前向聲明 (forward declared )
        刪除不必要的一大堆私有成員變量,轉而使用 ”impl” 方法
         刪除不必要的類之間的繼承
        為了講清楚這3點,還是舉個實例比較好,這個實例我會一步一步的改進(因為我也是一點一點摸索出來了,如果哪里說錯了, 你就放心的噴吧,我會和你在爭論到底的,呵呵)
        現在先假設你找到一個新工作,接手以前某個程序員寫的類,如下
        //  old.h: 這就是你接收的類
             //
             #include <iostream>
             #include <ostream>
             #include <list>

             // 5 個 分別是file , db, cx, deduce or error , 水平有限沒有模板類
             // 只用 file and cx 有虛函數.
             #include "file.h"  // class file
             #include "db.h"  // class db
             #include "cx.h"  // class cx
             #include "deduce.h"  // class deduce
             #include "error.h"  // class error

             class old : public file, private db {
             public:
                  old( const cx& );
               db  get_db( int, char* );
               cx  get_cx( int, cx );
               cx& fun1( db );
               error  fun2( error );
               virtual std::ostream& print( std::ostream& ) const;
             private:
               std::list<cx> cx_list_;
               deduce       deduce_d_;
             };
                inline std::ostream& operator<<( std::ostream& os,const old& old_val )
               { return old_val.print(os); }
        這個類看完了, 如果你已經看出了問題出在哪里, 接下來的不用看了, 你是高手, 這些基本知識對你來說太小兒科,要是像面試時被問住了愣了一下,請接著看吧

        先看怎么使用先進條: 刪除不必要的#include

        這個類引用 5個頭文件, 那意味著那5個頭文件所引用的頭文件也都被引用了進來, 實際上, 不需要引用5 個,只要引用2個就有效可以了

        1.刪除不必要的#include,替代辦法 使用前向聲明 (forward declared )

        1.1刪除頭文件 iostream, 我剛開始學習c++ 時照著《c++ primer》 抄,只要看見關于輸入,輸出就把 iostream 頭文件加上, 幾年過去了, 現在我知道不是這樣的, 這里只是定義輸出函數, 只要引用ostream 就夠了

        1.2.ostream頭文件也不要, 替換為 iosfwd , 為什么, 原因就是, 參數和返回類型只要前向聲明就可以編譯通過, 在iosfwd 文件里 678行(我的環境是vs2013,不同的編譯環境具體位置可能會不相同,但是都有這句聲明) 有這么一句

        typedef basic_ostream<char, char_traits<char> > ostream;

        inline std::ostream& operator<<( std::ostream& os,const old& old_val )

        { return old_val.print(os); }

        除此之外,要是你說這個函數要操作ostream 對象, 那還是需要#include <ostream> , 你只說對了一半, 的確, 這個函數要操作ostream 對象, 但是請看他的函數實現,

        里面沒有定義一個類似 std::ostream os, 這樣的語句,話說回來,但凡出現這樣的定義語句, 就必須#include 相應的頭文件了 ,因為這是請求編譯器分配空間,而如果只前向聲明 class XXX; 編譯器怎么知道分配多大的空間給這個對象!

        看到這里, old.h頭文件可以更新如下了:

        //  old.h: 這就是你接收的類
             //
             #include <iosfwd>  //新替換的頭文件
             #include <list>

             // 5 個 分別是file , db, cx, deduce or error , 水平有限沒有模板類
             // 只用 file and cx 有虛函數.
             #include "file.h"  // class file  , 作為基類不能刪除,刪除了編譯器就不知道實例化old 對象時分配多大的空間了
             #include "db.h"  // class db, 作為基類不能刪除,同上
             #include "cx.h"  // class cx
             #include "deduce.h"  // class deduce
             // error 只被用做參數和返回值類型, 用前向聲明替換#include  "error.h" 
             class error;

             class old : public file, private db {
             public:
                  old( const cx& );
               db  get_db( int, char* );
               cx  get_cx( int, cx );
               cx& fun1( db );
               error  fun2( error );
               virtual std::ostream& print( std::ostream& ) const;
             private:
               std::list<cx> cx_list_; //  cx 是模版類型,既不是函數參數類型也不是函數返回值類型,所以cx.h 頭文件不能刪除
               deduce       deduce_d_; //  deduce 是類型定義,也不刪除他的頭文件
             };
                inline std::ostream& operator<<( std::ostream& os,const old& old_val )
               { return old_val.print(os); }
        到目前為止, 刪除了一些代碼, 是不是心情很爽,據說看一個程序員的水平有多高, 不是看他寫了多少代碼,而是看他少寫了多少代碼。

        如果你對C++ 編程有更深一步的興趣, 接下來的文字你還是會看的,再進一步刪除代碼, 但是這次要另辟蹊徑了

        2. 刪除不必要的一大堆私有成員變量,轉而使用 ”impl” 方法

        2.1.使用 ”impl” 實現方式寫代碼,減少客戶端代碼的編譯依賴

        impl 方法簡單點說就是把 類的私有成員變量全部放進一個impl 類, 然后把這個類的私有成員變量只保留一個impl* 指針,代碼如下

        // file old.h
             class old {
                //公有和保護成員
               // public and protected members
             private:
             //私有成員, 只要任意一個的頭文件發生變化或成員個數增加,減少,所有引用old.h的客戶端必須重新編譯
               // private members; whenever these change,
               // all client code must be recompiled
             };
        改寫成這樣:

        // file old.h
             class old {
             //公有和保護成員
               // public and protected members
             private:
               class oldImpl* pimpl_;
               //  替換原來的所有私有成員變量為這個impl指針,指針只需要前向聲明就可以編譯通過,這種寫法將前向聲明和定義指針放在了一起, 有效可以。
               //當然,也可以分開寫
                 // a pointer to a forward-declared class
             };

             // file old.cpp
             struct oldImpl {
             //真正的成員變量隱藏在這里, 隨意變化, 客戶端的代碼都不需要重新編譯
               // private members; fully hidden, can be
               // changed at will without recompiling clients
             };
        不知道你看明白了沒有, 看不明白請隨便寫個類試驗下,我就是這么做的,當然凡事也都有優缺點,下面簡單對比下:

          使用impl 實現類 不使用impl實現類
        優點 類型定義與客戶端隔離, 減少#include 的次數,提高編譯速度,庫端的類隨意修改,客戶端不需要重新編譯 直接,簡單明了,不需要考慮堆分配,釋放,內存泄漏問題
        缺點 對于impl的指針必須使用堆分配,堆釋放,時間長了會產生內存碎片,較終影響程序運行速度, 每次調用一個成員函數都要經過impl->xxx()的快速轉發 庫端任意頭文件發生變化,客戶端都必須重新編譯
        改為impl實現后是這樣的:

        // 只用 file and cx 有虛函數.
             #include "file.h" 
             #include "db.h" 
             class cx;
             class error;

             class old : public file, private db {
             public:
                  old( const cx& );
               db  get_db( int, char* );
               cx  get_cx( int, cx );
               cx& fun1( db );
               error  fun2( error );
               virtual std::ostream& print( std::ostream& ) const;
             private:
        class oldimpl* pimpl; //此處前向聲明和定義
              };
                inline std::ostream& operator<<( std::ostream& os,const old& old_val )
               { return old_val.print(os); }

        //implementation file old.cpp
        class oldimpl{
        std::list<cx> cx_list_;
        deduce        dudece_d_;
        };
        3. 刪除不必要的類之間的繼承

        面向對象提供了繼承這種機制,但是繼承不要濫用, old class 的繼承就屬于濫用之一, class old 繼承file 和 db 類, 繼承file是公有繼承,繼承db 是私有繼承

        ,繼承file 可以理解, 因為file 中有虛函數, old 要重新定義它, 但是根據我們的假設, 只有file 和 cx 有虛函數,私有繼承db 怎么解釋?! 那么先進可能的理由就是:

        通過 私有繼承—讓某個類不能當作基類去派生其他類,類似Java里final關鍵字的功能,但是從實例看,顯然沒有這個用意, 所以這個私有繼承有效不必要, 應該改用包含的方式去使用db類提供的功能, 這樣就可以

        把”db.h”頭文件刪除, 把db 的實例也可以放進impl類中,較終得到的類是這樣的:

        // 只用 file and cx 有虛函數.
             #include "file.h" 
             class cx;
             class error;
             class db;
             class old : public file {
             public:
                  old( const cx& );
               db  get_db( int, char* );
               cx   get_cx( int, cx );
               cx& fun1( db );
               error  fun2( error );
               virtual std::ostream& print( std::ostream& ) const;
             private:
               class oldimpl* pimpl; //此處前向聲明和定義
              };
                inline std::ostream& operator<<( std::ostream& os,const old& old_val )
               { return old_val.print(os); }

        //implementation file old.cpp
        class oldimpl{
        std::list<cx> cx_list_;
        deduce        dudece_d_;
        };
        小結一下:
        這篇文章只是簡單的介紹了減少編譯時間的幾個辦法:
        1. 刪除不必要的#include,替代辦法 使用前向聲明 (forward declared )
        2. 刪除不必要的一大堆私有成員變量,轉而使用 ”impl” 方法
        3. 刪除不必要的類之間的繼承

        這幾條希望對您有所幫助, 如果我哪里講的不夠清楚也可以參考附件,哪里有完整的實例,也歡迎您發表評論, 大家一起討論進步,哦不,加薪。 呵呵,在下篇文章我將把impl實現方式再詳細分析下,期待吧…

        以上內容由至成科技(西安網站設計,西安網站制作)為您提供,更多精彩內容:http://www.vxdmg.com/

        關注“至成科技”微信公眾號,快速獲取互聯網較新資訊

        網友評論

        登錄后可評論,請登錄

        全部評論:0條

        掃描左側二維碼
        關注至成微信公眾號

        西安至成信息科技有限公司  Copyright 2012-2019  xazcit.com  All rights reserved.

        Email:[email protected]     郵政編碼:710016     《中華人民共和國增值電信業務經營許可證》陜B1.B2-20140011     陜ICP備12008874號-1

        聯系地址:西安市經開區鳳城四路西安國際企業中心B座23層06-10室    售前咨詢熱線:029-89390727    售后服務電話:029-89393039

        西安網站建設、網站設計制作公司-至成科技,已為眾多企業提供網站建設網站制作響應式網站設計手機網站建設虛擬主機云主機服務器租用等建站解決方案。

        網絡警察 12321垃圾信息舉報 不良信息舉報 中國文明網 西安工商
        ×
        安徽25选5计划