<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>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                # Item 41: 理解 implicit interfaces(隱式接口)和 compile-time polymorphism(編譯期多態) 作者:Scott Meyers 譯者:fatalerror99 (iTePub's Nirvana) 發布:http://blog.csdn.net/fatalerror99/ object-oriented programming(面向對象編程)的世界是圍繞著 explicit interfaces(顯式接口)和 runtime polymorphism(執行期多態)為中心的。例如,給出下面這個(沒有什么意義的)class(類), ``` class Widget { public: Widget(); virtual ~Widget(); virtual std::size_t size() const; virtual void normalize(); void swap(Widget& other); // see Item 25 ... }; ``` 以及這個(同樣沒有什么意義的)function(函數), ``` void doProcessing(Widget& w) { if (w.size() > 10 && w != someNastyWidget) { Widget temp(w); temp.normalize(); temp.swap(w); } } ``` 我們可以這樣談論 doProcessing 中的 w: * 因為 w 被聲明為 Widget 類型的引用,w 必須支持 Widget interface(接口)。我們可以在源代碼中找到這個 interface(接口)(例如,Widget 的 .h 文件)以看清楚它是什么樣子的,所以我們稱其為一個 explicit interface(顯式接口)——它在源代碼中顯式可見。 * 因為 Widget 的一些 member functions(成員函數)是虛擬的,w 對這些函數的調用就表現為 runtime polymorphism(執行期多態):被調用的特定函數在執行期基于 w 的 dynamic type(動態類型)來確定(參見 Item 37)。 templates(模板)和 generic programming(泛型編程)的世界是根本不同的。在那個世界,explicit interfaces(顯式接口)和 runtime polymorphism(執行期多態)繼續存在,但是它們不那么重要了。作為替代,把 implicit interfaces(隱式接口)和 compile-time polymorphism(編譯期多態)推到了前面。為了了解這是怎樣一種情況,看一下當我們把 doProcessing 從一個 function(函數)轉為一個 function template(函數模板)時會發生什么: ``` template<typename T> void doProcessing(T& w) { if (w.size() > 10 && w != someNastyWidget) { T temp(w); temp.normalize(); temp.swap(w); } } ``` 現在我們可以如何談論 doProcessing 中的 w 呢? * w 必須支持的 interface(接口)是通過 template(模板)中在 w 身上所執行的操作確定的。在本例中,它顯現為 w 的 type (T) 必須支持 size,normalize 和 swap member functions(成員函數);copy construction(拷貝構造函數)(用于創建 temp);以及對不等于的比較(用于和 someNastyWidget 之間的比較)。我們將在以后看到這并不很精確,但是對于現在來說它已經足夠正確了。重要的是這一系列必須有效地適合于模板編譯的表達式是 T 必須支持的 implicit interface(隱式接口)。 * 對諸如 operator&gt; 和 operator!= 這樣的包含 w 的函數的調用可能伴隨 instantiating templates(實例化模板)以使這些調用成功。這樣的 instantiation(實例化)發生在編譯期間。因為用不同的 template parameters(模板參數)實例化 function templates(函數模板)導致不同的函數被調用,因此以 compile-time polymorphism(編譯期多態)著稱。 即使你從沒有使用過模板,你也應該熟悉 runtime(運行期)和 compile-time polymorphism(編譯期多態)之間的區別,因為它類似于確定一系列重載函數中哪一個應該被調用的過程(這個發生在編譯期)和 virtual function(虛擬函數)調用的 dynamic binding(動態綁定)(這個發生在運行期)之間的區別。explicit(顯式)和 implicit interfaces(隱式接口)之間的區別是與 template(模板)有關的新內容,需要對他進行近距離的考察。 一個 explicit interface(顯式接口)由 function signatures(函數識別特征)組成,也就是說,函數名,參數類型,返回值,等等。例如,Widget class(類)的 public interface(顯式接口), ``` class Widget { public: Widget(); virtual ~Widget(); virtual std::size_t size() const; virtual void normalize(); void swap(Widget& other); }; ``` 由一個 constructor(構造函數),一個 destructor(析構函數),以及函數 size,normalize 和 swap 組成,再加上 parameter types(參數類型),return types(返回類型)和這些函數的 constnesses(常量性)。(它也包括 compiler-generated(編譯器生成)的 copy constructor(拷貝構造函數)和 copy assignment operator(拷貝賦值運算符)——參見 Item 5。)它還可能包含 typedefs,還有,如果你膽大包天敢于違背 Item 22 的讓 data members(數據成員)private(私有)的建議,即使在這種情況下,這些 data members(數據成員)也不是。 一個 implicit interface(隱式接口)有很大不同。它不是基于 function signatures(函數識別特征)的。它是由 valid expressions(合法表達式)組成的。再看一下在 doProcessing template 開始處的條件: ``` template<typename T> void doProcessing(T& w) { if (w.size() > 10 && w != someNastyWidget) { ... ``` 對于 T(w 的類型)的 implicit interface(隱式接口)看起來有如下這些約束: * 它必須提供一個名為 size 的返回一個正數值的 member function(成員函數)。 * 它必須支持一個用于比較兩個類型 T 的對象的 operator!= 函數。(這里,我們假定 someNastyWidget 的類型為 T。) 由于 operator overloading(運算符重載)的可能性,這兩個約束都不必滿足。是的,T 必須支持一個 size member function(成員函數),值得提及的是雖然這個函數可以是從一個 base class(基類)繼承來的。但是這個 member function(成員函數)不需要返回一個整數類型。它甚至不需要返回一個數值類型。對于這種情況,它甚至不需要返回一個定義了 operator&gt; 的類型!它要做的全部就是返回類型 X 的一個 object(對象),有一個 operator&gt; 可以用一個類型為 X 的 object(對象)和一個 int(因為 10 為 int 類型)來調用。這個 operator&gt; 不需要取得一個類型 X 的參數,因為它可以取得一個類型 Y 的參數,只要在類型 X 的 objects(對象)和類型 Y 的 objects(對象)之間有一個 implicit conversion(隱式轉型)就可以了! 類似地,T 支持 operator!= 也是沒有必要的,因為如果 operator!= 取得一個類型 X 的 objects(對象)和一個類型 Y 的 objects(對象)是可接受的一樣。只要 T 能轉型為 X,而 someNastyWidget 的類型能夠轉型為 Y,對 operator!= 的調用就是合法的。 (一個旁注:此處的分析沒有考慮 operator&& 被重載的可能性,這會將上面的表達式的含義從與轉換到某些大概完全不同的東西。) 第一次考慮 implicit interfaces(隱式接口)的時候,大多數人都會頭疼,但是他們真的不需要阿司匹林。implicit interfaces(隱式接口)簡單地由一套 valid expressions(合法表達式)構成。這些表達式自身看起來可能很復雜,但是它們施加的約束通常是簡單易懂的。例如,給出這個條件, ``` if (w.size() > 10 && w != someNastyWidget) ... ``` 關于 functions size,operator&gt;,operator&& 或 operator!= 上的約束很難說出更多的東西,但是要識別出整個表達式的約束是非常簡單的。一個 if 語句的條件部分必須是一個 boolean expression(布爾表達式),所以不管 "w.size() &gt; 10 && w != someNastyWidget" 所產生的類型涉及到的精確類型,它必須與 bool 兼容。這就是 template(模板)doProcessing 施加于它的 type parameter(類型參數)T 之上的 implicit interface(隱式接口)的一部分。被 doProcessing 需要的 interface(接口)的其余部分是 copy constructor(拷貝構造函數),normalize 和 swap 的調用對于類型 T 的 objects(對象)來說必須是合法的。 implicit interface(隱式接口)對 template(模板)的 parameters(參數)施加的影響正像 explicit interfaces(顯式接口)對一個 class(類)的 objects(對象)施加的影響,而且這兩者都在編譯期間被檢查。正像你不能用與它的 class(類)提供的 explicit interface(顯式接口)矛盾的方法使用 object(對象)(代碼無法編譯)一樣,除非一個 object(對象)支持 template(模板)所需要的 implicit interface(隱式接口),否則你就不能在一個 template(模板)中試圖使用這個 object(對象)(代碼還是無法編譯)。 Things to Remember * classes(類)和 templates(模板)都支持 interfaces(接口)和 polymorphism(多態)。 * 對于 classes(類),interfaces(接口)是 explicit(顯式)的并以 function signatures(函數識別特征)為中心的。polymorphism(多態性)通過 virtual functions(虛擬函數)出現在運行期。 * 對于 template parameters(模板參數),interfaces(接口)是 implicit(隱式)的并基于 valid expressions(合法表達式)。polymorphism(多態性)通過 template instantiation(模板實例化)和 function overloading resolution(函數重載解析)出現在編譯期。
                  <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>

                              哎呀哎呀视频在线观看