<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                34.將文件間的編譯依賴性降到最低。 對于一個大型程序,其結構是錯綜復雜的,當你對一個類進行一些改動時,修改的不是接口,而是類的實現,即只是一些細節部分,但重新生成程序時,所有用到這個類的的文件都要重新編譯。這里題目指的是這個意思。但實際上,我在vs2012實踐了一下,對于類B與類A相關聯,類B的實現依賴于類A,若類A的實現發生了改變,并不會影響B,即生成時,編譯器只會去重新編譯A,而對于依賴于A的用戶程序,并不會像其所說那樣全部重新編譯。好吧,我這里總算是明白其所說的修改其實現的意思了。 修改類的實現: 類的接口只是類中提供給外部的函數, 而類的實現是指類實現接口函數所需要的內部邏輯和數據結構,如一些私有的函數,以及一些私有的成員數據。修改這些類實現的,對于實現函數的修改就必須修改函數的聲明,而數據成員的修改就是數據成員的類型以及數量的修改。當進行這些修改時,就必定會導致調用這個類的用戶程序都要重新編譯。 一般的解決方法是將實現與接口分開,即對于本來使用的一個類,將其轉換為兩個類,一個類為接口類,供用戶程序調用,一個類為實現類,有具體的實現邏輯以及實現所需的數據成員,且接口類能夠指向對應的實現類,對于實現邏輯的更改不會影響用戶程序,因為用戶程序只與接口類連接,而隱藏了實現邏輯修改造成的影響,只有當接口改變時,才需要重新編譯。分離的關鍵是,對類定義的依賴 被 對類聲明的依賴取代,降低編譯依賴性,將 提供類定義 即#include 指令 的任務由原來的函數聲明頭文件轉交給包含函數調用的用戶文件。 即不在頭文件中包含其他頭文件,除非缺少它們就不能編譯,而一個一個地聲明所需要的類,讓使用這個頭文件的用戶自己通過include去包含這些頭文件,以使用戶代碼通過編譯。 實現這種接口與實現分離,在c++中一般有兩種方法,一種是 將一個對象的實現隱藏在指針的背后,即用一個指針指向某個不確定的實現。這樣的類稱為句柄類或信封類。而指向的實現類稱為 主體類或者信件類。句柄類,即接口只是將所有函數調用轉移到對應的主體類中,有主題類也就是實現類來真正完成工作。接口中要將原來的實現需要的數據成員轉換為函數,而去調用實現類中的數據成員 來實現功能,即接口中使用函數來實現對實現類中的數據成員實現傳遞和返回。 假如簡單實現兩個類,A ,B,C,A中放一個int,b中放一個doubel,C中放兩者之和,寫出代碼如下: classA.h: ~~~ #pragma once class ClassA{ public: public: int a; ClassA(int x){a = x;} ClassA(){a = 0;} int getA() const{return a;}; }; ~~~ ClassB.h: ~~~ class ClassB{ public: double b; double getB() const{return b;} ClassB(double x){b = x;} ClassB(){b = 0;} }; ~~~ ClassC.h,即接口: ~~~ //這個頭文件就是所謂的接口,如此將接口與實現分離后,只有修改接口時,才會導致使用該接口的用戶程序重新編譯 class ClassA;//只聲明,在接口中只要知道有這些類,而在實現中才去include這些頭文件 class ClassB; class ClassCImpl; class ClassC{ public: ClassC(const ClassA& xa,const ClassB& xb); virtual ~ClassC(); int getA() const;//函數來返回實現類中的數據成員 double getB() const; double getC() const; private: ClassCImpl *impl;//使用指針來指向實現類 //int aaa;//在接口中任意進行修改,就要重新編譯其與其用戶程序 }; ~~~ ClassC.cpp,接口的函數,調用 實現類中的函數進行返回。 ~~~ //這里也是對于接口的實現,修改這里的數據,不會導致其他程序的重新編譯 #include "ClassC.h"//這是接口ClassC的函數具體實現 #include "ClassCImpl.h"//要包含實現類的定義,且實現類中與ClassC中有一樣的成員函數 ClassC::ClassC(const ClassA& xa,const ClassB& xb){ impl = new ClassCImpl(xa,xb); } ClassC::~ClassC(){ delete impl; } int ClassC::getA() const{ return impl->getA(); } double ClassC::getB() const{ return impl->getB(); } double ClassC::getC() const{ return impl->getC(); } ~~~ ClassCImpl ,實現類的定義: ~~~ #include "ClassA.h" #include "ClassB.h" class ClassCImpl{ public: ClassCImpl(const ClassA& xa,const ClassB& xb); int getA() const;//函數實現接口中函數 double getB() const; double getC() const; private: ClassA A; ClassB B; ClassB C; }; ~~~ ClassCImpl.cpp,實現類的簡單的操作: ~~~ #include "ClassCImpl.h"//要包含實現類的定義,且實現類中與ClassC中有一樣的成員函數 ClassCImpl::ClassCImpl(const ClassA& xa,const ClassB& xb){ A = xa; B = xb; C = (B.getB() + A.getA()); } int ClassCImpl::getA() const{ return A.getA(); } double ClassCImpl::getB() const{ return B.getB(); } double ClassCImpl::getC() const{ return C.getB(); } ~~~ 這樣就實現了接口與實現的分離,在ClassC中定義接口,在接口固定的情況下,在接口實現類ClassCImpl中進行任意的修改,編譯器都只會重新編譯實現類,而不會全部重新編譯。這是使用句柄類實現的接口與實現分離。 另外一種方法成為協議類,即是這個類成為特殊類型的抽象基類。協議類只是為派生類確定接口,它沒有數據成員,沒有構造函數,有一個虛析構函數,有一些純虛函數,這些純虛函數組成了接口。 協議類的用戶通過一個類似構造函數的的函數來創建新的對象,而這個構造函數所在的類就是隱藏在后的派生類。這種函數一般稱為工廠函數,返回一個指針,指向支持協議類接口的派生類的動態分配對象。這個工廠函數與協議類解密相連,所以一般將它聲明為協議類的靜態成員。若重新聲明一個ClassD,完成之前的功能,,但是為一個協議類,有: ClassD.h: ~~~ //這個為協議類 class ClassA;//只聲明,在接口中只要知道有這些類,而在實現中才去include這些頭文件 class ClassB; class ClassD{ public: virtual ~ClassD(){} virtual int getA() const = 0;//函數來返回實現類中的數據成員 virtual double getB() const = 0; virtual double getD() const = 0; static ClassD* makeClassD(const ClassA& xa,const ClassB& xb);//這里使用靜態成員來返回 }; ~~~ 再寫一個派生類來實現CLassD的功能,RealClassD.h: ~~~ #include "ClassA.h" #include "ClassB.h" #include "ClassD.h" class RealClassD:public ClassD{ public: RealClassD(const ClassA& xa,const ClassB& xb):A(xa),B(xb),D(B.getB() + A.getA()){} virtual ~RealClassD(){} int getA() const; double getB() const ; double getD() const; private: ClassA A; ClassB B; ClassB D; }; ~~~ 而在這個派生類定義中,順帶實現ClassD中的返回指針的makeClassD的函數。這里:先從協議類中繼承接口規范,然后在實現中實現接口中的函數。 ~~~ #include "RealClassD.h" int RealClassD::getA() const{ return A.getA(); } double RealClassD::getB() const{ return B.getB(); }; double RealClassD::getD() const{ return D.getB(); } ClassD* ClassD::makeClassD(const ClassA& xa,const ClassB& xb){ return new RealClassD(xa,xb); } ~~~ 而在需要使用的地方,如此調用這個函數來指向需要的接口: ~~~ ClassD* dd = ClassD::makeClassD(a,b); cout<<dd->getD()<<endl; ~~~ dd的指針動態綁定到返回的派生類對象,而在派生類中修改其實現的成員只要重新編譯派生類的cpp就行了。 句柄類和協議類分離了接口與實現,從而降低了文件間的依賴性,當一定程度上有時間和空間上的消耗。對于一個程序轉變為產品時,要用具體的類來取代句柄類和協議類。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看