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

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                # Item 38: 通過 composition(復合)模擬 "has-a"(有一個)或 "is-implemented-in-terms-of"(是根據……實現的) 作者:Scott Meyers 譯者:fatalerror99 (iTePub's Nirvana) 發布:http://blog.csdn.net/fatalerror99/ composition(復合)是在 objects of one type(一個類型的對象)包含 objects of another type(另一個類型的對象)時,types(類型)之間的關系。例如: ``` class Address { ... }; // where someone lives class PhoneNumber { ... }; class Person { public: ... private: std::string name; // composed object Address address; // ditto PhoneNumber voiceNumber; // ditto PhoneNumber faxNumber; // ditto }; ``` 此例之中,Person objects(對象)由 string,Address,和 PhoneNumber objects(對象)組成。在程序員中,術語 composition(復合)有很多同義詞。它也可以稱為 layering,containment,aggregation,和 embedding。 Item 32 解釋了 public inheritance(公有繼承)意味著 "is-a"(是一個)。composition(復合)也有一個含意。實際上,他有兩個含意。composition(復合)既意味著 "has-a"(有一個),又意味著 "is-implemented-in-terms-of"(是根據……實現的)。這是因為你要在你的軟件中處理兩個不同的 domains(領域)。你程序中的一些 objects(對象)對應你所模擬的世界里的東西,例如,people(人),vehicles(交通工具),video frames(視頻畫面)等等。這樣的 objects(對象)是 application domain(應用領域)的部分。另外的 objects(對象)純粹是 implementation artifacts(實現的產物),例如,buffers(緩沖區),mutexes(互斥體),search trees(搜索樹)等等。這些各類 objects(對象)定義應你的軟件的 implementation domain(實現領域)。當 composition(復合)發生在 application domain(應用領域)的 objects(對象)之間,它表達一個 has-a(有一個)的關系,當它發生在 implementation domain(實現領域),它表達一個 is-implemented-in-terms-of(是根據……實現的)的關系 上面的 Person class(類)示范了 has-a(有一個)的關系。一個 Person object(對象)has a(有一個)名字,一個地址,以及語音和傳真電話號碼。你不能說一個人 is a(是一個)名字或一個人 is an(是一個)地址。你可以說一個人 has a(有一個)名字和 has an(有一個)地址。大多數人對此區別不難理解,所以混淆 is-a(是一個)和 has-a(有一個)之間的角色的情況非常少見。 is-a(是一個)和 is-implemented-in-terms-of(是根據……實現的)之間的區別稍微有些棘手。例如,假設你需要一個類的模板來表現相當小的 objects(對象)的 sets,也就是說,排除重復的集合。因為 reuse(復用)是一件受人歡迎的事情,你的第一個直覺就是使用標準庫中的 set template(模板)。當你能使用已經被寫好的東西時,為什么還要寫一個新的 template(模板)呢? 不幸的是,set 的典型實現導致每個元素三個指針的開銷。這是因為 sets 通常被作為 balanced search trees(平衡搜索樹)來實現,這允許它們保證 logarithmic-time(對數時間)的 lookups(查找),insertions(插入)和 erasures(刪除)。當速度比空間更重要的時候,這是一個合理的設計,但是當空間比速度更重要時,對你的程序來說就有問題了。因而,對你來說,標準庫的 set 為你提供了不合理的交易。看起來你終究還是要寫你自己的 template(模板)。 reuse(復用)依然是一件受人歡迎的事情。作為 data structure(數據結構)的專家,你知道實現 sets 的諸多選擇,其中一種是使用 linked lists(線性鏈表)。你也知道標準的 C++ 庫中有一個 list template(模板),所以你決定(復)用它。 具體地說,你決定讓你的新的 Set template(模板)從 list 繼承。也就是說,Set&lt;T&gt; 將從 list&lt;T&gt; 繼承。畢竟,在你的實現中,一個 Set object(對象)實際上就是一個 list object(對象)。于是,你就像這樣聲明你的 Set template(模板): ``` template<typename T> // the wrong way to use list for Set class Set: public std::list<T> { ... }; ``` 在這里,看起來每件事情都很好。但實際上有一個很大的錯誤。就像 Item 32 中的解釋,如果 D is-a(是一個)B,對于 B 成立的每一件事情對 D 也成立。然而,一個 list object(對象)可以包含重復,所以如果值 3051 被插入一個 list&lt;int&gt; 兩次,那個 list 將包含 3051 的兩個拷貝。與此對照,一個 Set 不可以包含重復,所以如果值 3051 被插入一個 Set&lt;int&gt; 兩次,那個 set 只包含該值的一個拷貝。因此一個 Set is-a(是一個)list 是不正確的,因為對 list objects(對象)成立的某些事情對 Set objects(對象)不成立。 因為這兩個 classes(類)之間的關系不是 is-a(是一個),public inheritance(公有繼承)不是模擬這個關系的正確方法。正確的方法是認識到一個 Set object(對象)可以 be implemented in terms of a list object(是根據一個 list 對象實現的): ``` template<class T> // the right way to use list for Set class Set { public: bool member(const T& item) const; void insert(const T& item); void remove(const T& item); std::size_t size() const; private: std::list<T> rep; // representation for Set data }; ``` Set 的 member functions(成員函數)可以極大程度地依賴 list 和標準庫的其它部分已經提供的機能,所以只要你熟悉了用 STL 編程的基本方法,實現就非常簡單了: ``` template<typename T> bool Set<T>::member(const T& item) const { return std::find(rep.begin(), rep.end(), item) != rep.end(); } template<typename T> void Set<T>::insert(const T& item) { if (!member(item)) rep.push_back(item); } template<typename T> void Set<T>::remove(const T& item) { typename std::list<T>::iterator it = // see Item 42 for info on std::find(rep.begin(), rep.end(), item); // "typename" here if (it != rep.end()) rep.erase(it); } template<typename T> std::size_t Set<T>::size() const { return rep.size(); } ``` 這些函數足夠簡單,使它們成為 inlining(內聯化)的合理候選者,可是我知道在堅定 inlining(內聯化)的決心之前,你可能需要回顧一下 Item 30 中的討論。 一個有說服力的觀點是,根據 Item 18 的關于將 interfaces(接口)設計得易于正確使用,而難以錯誤使用的論述,如果要遵循 STL container(容器)的慣例,Set 的 interface(接口)應該更多,但是在這里遵循那些慣例就需要在 Set 中填充大量 stuff(材料),這將使得它和 list 之間的關系變得曖昧不清。因為這個關系是本 Item 的重點,我們用教學的清晰性替換了 STL 的兼容性。除此之外,Set 的 interface(接口)的幼稚不應該遮掩關于 Set 的無可爭辯的正確:它和 list 之間的關系。這個關系不是 is-a(是一個)(雖然最初看上去可能很像),而是 is-implemented-in-terms-of(是根據……實現的)。 Things to Remember * composition(復合)與 public inheritance(公有繼承)的意義完全不同。 * 在 application domain(應用領域)中,composition(復合)意味著 has-a(有一個)。在 implementation domain(實現領域)中意味著 is-implemented-in-terms-of(是根據……實現的)。
                  <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>

                              哎呀哎呀视频在线观看