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

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                38.絕不要重新定義繼承而來的缺省參數值。 重新定義函數缺省參數值意味著重新定義函數,而非虛函數不能重新定義,所以將就考慮不能重新定義虛函數的缺省參數值的原因:虛函數是動態綁定的而缺省參數值是靜態綁定的。 靜態類型是指程序中聲明的類型,而動態類型是指實際對象的類型,舉個栗子: ~~~ class A{ public: virtual void fun(int a=0) const{cout<<a<<endl;} }; class B:public A{ public: virtual void fun(int a =2)const{cout<<a<<endl;} }; int main(){ B* pb = new B();//pb的靜態類型為 B* A* pa = pb;//pa 的靜態類型 為 A*, //但是一個指針的靜態類型不一定為其動態類型,如pa它的動態類型卻是B類型的對象,這是由動態綁定實現的 pb->fun(); pa->fun(); ~~~ 虛函數是動態綁定的,但缺省參數值是靜態綁定的,即對于pb,pa調用的虛函數,其使用的默認參數值都為靜態綁定的,pa綁定的是 A類中的 a= 0,而pb綁定的是B類中的 a=2,兩者不同,雖然函數都是調用B中動態綁定的虛函數,但是默認參數不同,輸出結果也不同。 39.避免 ”向下轉換“ 繼承層次。 從一個基類指針到一個派生類指針稱為向下轉換,一般使用static_cast將基類指針強制轉換為派生類指針。向下轉換難看,容易導致錯誤,且難以理解,升級和維護。 向下轉換的消除:使用虛函數調用來代替。第一種方法很簡單理解,但是對于一些類不適用,如基類范圍太大導致7有些派生類不應該有這個函數的功能,所以要將這些類的每個虛函數稱為一個空操作,或者作為一個純虛函數,并默認實現返回錯誤的操作。第二個方法是加強類型約束,使得指針的聲明類型和你所知道的真的指針類型相同。即對于用到這些向下轉換時,通過一些設定,濾去那些不擁有真正指針類型的指針,只留下需要進行操作的指針并以其真實的類型來調用其函數。 如果遇到必須要轉換的情況,也不要使用static_cast,而是使用安全的用于多態的向下轉換 dynamic_cast,當對一個指針使用dynamic_cast時,先嘗試轉換,如果成功返回一個合法的指針,否則返回空指針。 40.通過分層來體現”有一個“或”用..來實現“。 使某個類的對象成為另一個類的數據成員,從而實現將一個類構筑在另一個類之上,這個稱為分層 Layering,也被稱為構成,包含或嵌入。 對于有一個的概念很容易理解,對于一個 Person, 有 Name,Address,Phone等屬性,但是不能說Person是一個Name。 對于"用..來實現”,其實就是調用其它類的對象作為類的主要數據成員,使用這個類的的函數接口來實現新的類中的功能與接口。 41.區分模版和繼承。 根據依賴的類的用途來區分,如過依賴的類是類的行為,則為繼承,如果依賴的類是類所操作的對象類型,則是模版。如,企鵝類依賴于鳥類,鳥類中的接口決定的是企鵝類中的行為,即兩者是繼承關系,而當實現一個集合時,集合類依賴與類T,是由于類T為集合類的進行操作的對象,這是模版。模版的實現會假設類可以調用T的構造析構賦值等函數,模版的特性是類模版的行為在任何地方都不依賴于T,行為不依賴于類型。 當對象的類型不影響類中函數的行為時,就使用模版來生成這樣一組類。 當對象的類型影響類中函數的行為時,就用繼承來得到這樣一組類。 42.明智地使用私有繼承。 私有繼承不為 “是一個” 的關系。如果兩個類之間的繼承關系為私有繼承,編譯器一般不會將派生類對象轉換為基類對象。私有繼承時,基類的公有和protected 類型的成員都變成派生類的私有成員。私有繼承意味著”用...實現“,私有繼承純粹是一種實現 技術。私有繼承只是繼承實現,而忽略接口。私有繼承在 軟件 ”設計“過程中毫無意義,只是在軟件”實現“時才有用。 對于分層,也有 用...實現的含義,對于分層與私有繼承,盡可能使用分層,必要時才使用私有繼承。而建議使用私有繼承在用到保護成員和有虛函數介入時。 對于一個基類,只作為其他類的實現來使用,使用分層作為其他類的私有成員,但其不是抽象類,導致其可能被其他人隨意調用導致出錯。這是就需要使用到私有繼承,對于這種具有實現但是只能用于特定用途的基類,將其接口都改為protected類型,而正確使用它的類不用分層而使用私有繼承來安全的使用基類。 對于模版,其為C++中最有用的組成部分之一,但是,實例化一個模版,就可能實例化實現這個模版的代碼,如構成set<int> 和set<double>的代碼是完全分開的兩份代碼,模版會導致代碼膨脹。改進的方法:創建一個通用類,儲存對象的void*指針。創建另一組類來保證類型安全使用通用類。以實現棧stack為例,先構建一個stack的通用類: ~~~ class GenericStack{ protected://實現類使用私有繼承繼承這個通用類,所以將接口保護起來 GenericStack(); ~GenericStack(); void push(void* object);//使用指針 void* pop(); bool empty() const; private: struct StackNode{ void *data; StackNode *next; //在stack中使用指針來傳遞數據和保存數據,則節點析構時不用釋放void指針指向的內存。 StackNode(void *newData,StackNode *nextNode) :data(newData),next(nextNode){} }; StackNode *top; GenericStack(const GenericStack&);//防止拷貝和賦值 GenericStack& operator=(const GenericStack&); }; ~~~ 而要實現stack的具體類通過私有繼承這個類來實現功能,而且可以使用模版來完美的完成這個工作: ~~~ template <class T> class Stack:private GenericStack{ public: void push(T* objectPtr){GenericStack::push(objectPtr);} T* pop(){return static_cast<T*>(GenericStack::pop());} bool empty() const {return GenericStack::empty();} }; ~~~ 這里使用私有繼承,將通用類GenericStatck作為其實現,而其接口函數都是內聯函數,幾乎沒有消耗,而且使用模版實現了類型安全的判斷。對于創建任意類型的stack只要重新編譯這個三個簡單的內聯函數即可,而不是通用類中復雜的實現,極大的降低了程序的開銷。 這樣的代碼是令人驚嘆的,近乎完美的。首先使用了模版,編譯器會根據你的需要來自動生成所有的接口。因為使用模版,這些類是類型安全的,類型錯誤會在編譯期間就能發現。因為GenericStack的成員函數是保護類型,用戶不可能繞過接口類來調用它。因為這個模版的接口成員函數都被隱式的聲明為內聯,使用這些類時不會帶來運行開銷,生成代碼就想用戶直接使用GenericStack來編寫的一樣。因為GenericStack是使用void*指針,操作棧的代碼只需要一份,而不同類型只要簡單的編譯類模版中的簡單的內聯函數就行。簡而言之,這個設計使代碼達到了最高的效率和最高的類型安全。
                  <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>

                              哎呀哎呀视频在线观看