<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國際加速解決方案。 廣告
                # Item 45: 用 member function templates(成員函數模板) 接受 "all compatible types"(“所有兼容類型”) 作者:Scott Meyers 譯者:fatalerror99 (iTePub's Nirvana) 發布:http://blog.csdn.net/fatalerror99/ smart pointers(智能指針)是行為很像指針但是增加了指針沒有提供的功能的 objects。例如,Item 13 闡述了標準 auto_ptr 和 tr1::shared_ptr 是怎樣被應用于在恰當的時間自動刪除的 heap-based resources(基于堆的資源)的。STL containers 內的 iterators(迭代器)幾乎始終是 smart pointers(智能指針);你絕對不能指望用 "++" 將一個 built-in pointer(內建指針)從一個 linked list(線性鏈表)的一個節點移動到下一個,但是 list::iterators 可以做到。 real pointers(真正的指針)做得很好的一件事是支持 implicit conversions(隱式轉換)。derived class pointers(派生類指針)隱式轉換到 base class pointers(基類指針),pointers to non-const objects(指向非常量對象的指針)轉換到 pointers to const objects(指向常量對象的指針),等等。例如,考慮在一個 three-level hierarchy(三層繼承體系)中能發生的一些轉換: ``` class Top { ... }; class Middle: public Top { ... }; class Bottom: public Middle { ... }; Top *pt1 = new Middle; // convert Middle* => Top* Top *pt2 = new Bottom; // convert Bottom* => Top* const Top *pct2 = pt1; // convert Top* => const Top* ``` 在 user-defined smart pointer classes(用戶定義智能指針類)中模仿這些轉換是需要技巧的。我們要讓下面的代碼能夠編譯: ``` template<typename T> class SmartPtr { public: // smart pointers are typically explicit SmartPtr(T *realPtr); // initialized by built-in pointers ... }; SmartPtr<Top> pt1 = // convert SmartPtr<Middle> => SmartPtr<Middle>(new Middle); // SmartPtr<Top> SmartPtr<Top> pt2 = // convert SmartPtr<Bottom> => SmartPtr<Bottom>(new Bottom); // SmartPtr<Top> SmartPtr<const Top> pct2 = pt1; // convert SmartPtr<Top> => // SmartPtr<const Top> ``` 在同一個 template(模板)的不同 instantiations(實例化)之間沒有 inherent relationship(繼承關系),所以編譯器認為 SmartPtr&lt;Middle&gt; 和 SmartPtr&lt;Top&gt; 是完全不同的 classes,并不比(比方說)vector&lt;float&gt; 和 Widget 的關系更近。為了得到我們想要的在 SmartPtr classes 之間的轉換,我們必須顯式地為它們編程。 在上面的 smart pointer(智能指針)的示例代碼中,每一個語句創建一個新的 smart pointer object(智能指針對象),所以現在我們就集中于我們如何寫 smart pointer constructors(智能指針的構造函數),讓它以我們想要的方式運轉。一個關鍵的事實是我們無法寫出我們需要的全部 constructors(構造函數)。在上面的 hierarchy(繼承體系)中,我們能從一個 SmartPtr&lt;Middle&gt; 或一個 SmartPtr&lt;Bottom&gt; 構造出一個 SmartPtr&lt;Top&gt;,但是如果將來這個 hierarchy(繼承體系)被擴充,SmartPtr&lt;Top&gt; objects 還必須能從其它 smart pointer types(智能指針類型)構造出來。例如,如果我們后來加入 ``` class BelowBottom: public Bottom { ... }; ``` 我們就需要支持從 SmartPtr&lt;BelowBottom&gt; objects 到 SmartPtr&lt;Top&gt; objects 的創建,而且我們當然不希望為了做到這一點而必須改變 SmartPtr template。 大體上,我們需要的 constructors(構造函數)的數量是無限的。因為一個 template(模板)能被實例化而產生無數個函數,所以好像我們不需要為 SmartPtr 提供一個 constructor function(構造函數函數),我們需要一個 constructor template(構造函數模板)。這樣的 templates(模板)是 member function templates(成員函數模板)(常常被恰如其分地稱為 member templates(成員模板))——生成一個 class 的 member functions(成員函數)的 templates(模板)的范例: ``` template<typename T> class SmartPtr { public: template<typename U> // member template SmartPtr(const SmartPtr<U>& other); // for a "generalized ... // copy constructor" }; ``` 這就是說對于每一種類型 T 和每一種類型 U,都能從一個 SmartPtr&lt;U&gt; 創建出一個 SmartPtr&lt;T&gt;,因為 SmartPtr&lt;T&gt; 有一個取得一個 SmartPtr&lt;U&gt; 參數的 constructor(構造函數)。像這樣的 constructor(構造函數)——從一個類型是同一個 template(模板)的不同實例化的 object 創建另一個 object 的 constructor(構造函數)(例如,從一個 SmartPtr&lt;U&gt; 創建一個 SmartPtr&lt;T&gt;)——有時被稱為 generalized copy constructors(泛型化拷貝構造函數)。 上面的 generalized copy constructor(泛型化拷貝構造函數)沒有被聲明為 explicit(顯式)的。這是故意為之的。built-in pointer types(內建指針類型)之間的類型轉換(例如,從派生類指針到基類指針)是隱式的和不需要 cast(強制轉型)的,所以讓 smart pointers(智能指針)模仿這一行為是合理的。在 templatized constructor(模板化構造函數)中省略 explicit 正好做到這一點。 作為聲明,SmartPtr 的 generalized copy constructor(泛型化拷貝構造函數)提供的東西比我們想要的還多。是的,我們需要能夠從一個 SmartPtr&lt;Bottom&gt; 創建一個 SmartPtr&lt;Top&gt;,但是我們不需要能夠從一個 SmartPtr&lt;Top&gt; 創建一個 SmartPtr&lt;Bottom&gt;,這就像顛倒 public inheritance(公有繼承)的含義(參見 Item 32)。我們也不需要能夠從一個 SmartPtr&lt;double&gt; 創建一個 SmartPtr&lt;int&gt;,因為這和從 int\* 到 double\* 的 implicit conversion(隱式轉換)是不相稱的。我們必須設法過濾從這個 member template(成員模板)生成的 member functions(成員函數)的群體。 假如 SmartPtr 跟隨 auto_ptr 和 tr1::shared_ptr 的腳步,提供一個返回被這個 smart pointer(智能指針)持有的 built-in pointer(內建指針)的拷貝的 get member function(get 成員函數)(參見 Item 15),我們可以用 constructor template(構造函數模板)的實現將轉換限定在我們想要的范圍: ``` template<typename T> class SmartPtr { public: template<typename U> SmartPtr(const SmartPtr<U>& other) // initialize this held ptr : heldPtr(other.get()) { ... } // with other's held ptr T* get() const { return heldPtr; } ... private: // built-in pointer held T *heldPtr; // by the SmartPtr }; ``` 我們通過 member initialization list(成員初始化列表),用 SmartPtr&lt;U&gt; 持有的類型為 U\* 的指針初始化 SmartPtr&lt;T&gt; 的類型為 T\* 的 data member(數據成員)。這只有在“存在一個從一個 U\* 指針到一個 T\* 指針的 implicit conversion(隱式轉換)”的條件下才能編譯,而這正是我們想要的。最終的效果就是 SmartPtr&lt;T&gt; 現在有一個 generalized copy constructor(泛型化拷貝構造函數),它只有在傳入一個 compatible type(兼容類型)的參數時才能編譯。 member function templates(成員函數模板)的用途并不限于 constructors(構造函數)。它們的另一個常見的任務是用于支持 assignment(賦值)。例如,TR1 的 shared_ptr(再次參見 Item 13)支持從所有兼容的 built-in pointers(內建指針),tr1::shared_ptrs,auto_ptrs 和 tr1::weak_ptrs(參見 Item 54)構造,以及從除 tr1::weak_ptrs 以外所有這些賦值。這里是從 TR1 規范中摘錄出來的一段關于 tr1::shared_ptr 的內容,包括它在聲明 template parameters(模板參數)時使用 class 而不是 typename 的偏好。(就像 Item 42 中闡述的,在這里的上下文環境中,它們的含義嚴格一致。) ``` template<class T> class shared_ptr { public: template<class Y> // construct from explicit shared_ptr(Y * p); // any compatible template<class Y> // built-in pointer, shared_ptr(shared_ptr<Y> const& r); // shared_ptr, template<class Y> // weak_ptr, or explicit shared_ptr(weak_ptr<Y> const& r); // auto_ptr template<class Y> explicit shared_ptr(auto_ptr<Y>& r); template<class Y> // assign from shared_ptr& operator=(shared_ptr<Y> const& r); // any compatible template<class Y> // shared_ptr or shared_ptr& operator=(auto_ptr<Y>& r); // auto_ptr ... }; ``` 除了 generalized copy constructor(泛型化拷貝構造函數),所有這些 constructors(構造函數)都是 explicit(顯式)的。這就意味著從 shared_ptr 的一種類型到另一種的 implicit conversion(隱式轉換)是被允許的,但是從一個 built-in pointer(內建指針)或其 smart pointer type(智能指針類型)的 implicit conversion(隱式轉換)是不被許可的。(explicit conversion(顯式轉換)——例如,經由一個 cast(強制轉型)——還是可以的。)同樣引起注意的是 auto_ptrs 被傳送給 tr1::shared_ptr 的 constructors(構造函數)和 assignment operators(賦值操作符)的方式沒有被聲明為 const,于此對照的是 tr1::shared_ptrs 和 tr1::weak_ptrs 的被傳送的方式。這是 auto_ptrs 被復制時需要獨一無二的被改變的事實的一個必然結果(參見 Item 13)。 member function templates(成員函數模板)是一個極好的東西,但是它們沒有改變這個語言的基本規則。Item 5 闡述的編譯器可以產生的四個 member functions(成員函數)其中兩個是 copy constructor(拷貝構造函數)和 copy assignment operator(拷貝賦值運算符)。tr1::shared_ptr 聲明了一個 generalized copy constructor(泛型化拷貝構造函數),而且很明顯,當類型 T 和 Y 相同時,generalized copy constructor(泛型化拷貝構造函數)就能被實例化而成為 "normal" copy constructor(“常規”拷貝構造函數)。那么,當一個 tr1::shared_ptr object 從另一個相同類型的 tr1::shared_ptr object 構造時,編譯器是為 tr1::shared_ptr 生成一個 copy constructor(拷貝構造函數),還是實例化 generalized copy constructor template(泛型化拷貝構造函數模板)? 就像我說過的,member templates(成員模板)不改變語言規則,而且規則規定如果一個 copy constructor(拷貝構造函數)是必需的而你沒有聲明,將為你自動生成一個。在一個 class 中聲明一個 generalized copy constructor(泛型化拷貝構造函數)(一個 member template(成員模板))不會阻止編譯器生成它們自己的 copy constructor(拷貝構造函數)(非模板的),所以如果你要全面支配 copy construction(拷貝構造),你必須既聲明一個 generalized copy constructor(泛型化拷貝構造函數)又聲明一個 "normal" copy constructor(“常規”拷貝構造函數)。這同樣適用于 assignment(賦值)。這是從 tr1::shared_ptr 的定義中摘錄的一段,可以作為例子: ``` template<class T> class shared_ptr { public: shared_ptr(shared_ptr const& r); // copy constructor template<class Y> // generalized shared_ptr(shared_ptr<Y> const& r); // copy constructor shared_ptr& operator=(shared_ptr const& r); // copy assignment template<class Y> // generalized shared_ptr& operator=(shared_ptr<Y> const& r); // copy assignment ... }; ``` Things to Remember * 使用 member function templates(成員函數模板)生成接受所有兼容類型的函數。 * 如果你為 generalized copy construction(泛型化拷貝構造)或 generalized assignment(泛型化賦值)聲明了 member templates(成員模板),你依然需要聲明 normal copy constructor(常規拷貝構造函數)和 copy assignment operator(拷貝賦值運算符)。
                  <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>

                              哎呀哎呀视频在线观看