<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          分享一個編程設(shè)計小技巧(沒有兩三年工作經(jīng)驗估計看不懂)

          共 1955字,需瀏覽 4分鐘

           ·

          2021-10-12 13:21

          直奔主題。


          假設(shè)有這樣的一個需求,要給Animal類添加一個方法,如果一種動物可以吃掉另一種動物,則返回true,否則返回false。


          接口可能會是下面這樣:

          struct?Animal?{????virtual?bool?eat(const?Animal&?animal)?const =?0;};

          那怎么實現(xiàn)呢?肯定是多態(tài),估計你能想到的第一種方法就是這樣:


          基類Animal的每個派生類都實現(xiàn)eat方法,然后根據(jù)參數(shù)運行時類型返回適當?shù)闹怠?/span>


          如何獲取參數(shù)類型呢?需要使用typeid。


          代碼如下:

          bool?Dog::eat(const?Animal&?animal)?const {????if?(typeid(animal)?==?typeid(Cat))?{????????return?true;????}?else?if?(typeid(animal)?==?typeid(Lion))?{????????return?false;????}????return?false;}
          bool?Lion::eat(const?Animal&?animal)?const {?return?true;?}
          bool?Cat::eat(const?Animal&?animal)?const {?return?false;?}

          這種方法可以滿足需求,但也只適用于類的數(shù)量比較少的情況。如果類的數(shù)量太多,每個重寫的方法實現(xiàn)體里面都會有特別多的if-else。關(guān)于if-else的弊端我之前介紹過,可以看看這里:少寫點if-else吧,它的效率有多低你知道嗎?


          這里還有些其他的問題:

          1. 隨著類數(shù)量的增加,這種代碼會變得很亂,不容易維護。

          2. 如果添加了新類型,這種方式不會強制要求派生類考慮新類型,假如新添加了Bear類,如果在某一個派生類里忘記處理Bear類,結(jié)果就可能有誤。

          3. typeid這種東西很雞肋,就不像個純粹的面向?qū)ο蠼Y(jié)構(gòu)。


          那是不是可以這樣做?

          struct?Animal?{????virtual?bool?eat(const?Dog&)?const =?0;????virtual?bool?eat(const?Cat&)?const =?0;????virtual?bool?eat(const?Lion&)?const =?0;};

          然后每個派生類重寫相應(yīng)的方法,這種方法貌似可行,但是只有單方向多態(tài),真正使用起來會有些不方便。而此方法的使用一定要這樣:

          animal.eat(cat);animal.eat(dog);animal.eat(lion);

          真正的雙方向多態(tài)使用方式應(yīng)該是這樣:

          animal1.eat(animal2);


          上面的方法還是不滿足需求。


          可以考慮這種方式:

          struct?Dog;struct?Cat;struct?Lion;
          struct?Animal?{????virtual?bool?eat(const?Animal&)?const?=?0;
          ????virtual?bool?eatenBy(const?Dog&)?const?=?0;????virtual?bool?eatenBy(const?Cat&)?const?=?0;????virtual?bool?eatenBy(const?Lion&)?const?=?0;};
          struct?Dog?:?public?Animal?{????bool?eat(const?Animal&?animal)?const?override?{?return?animal.eatenBy(*this);?}
          ????bool?eatenBy(const?Dog&)?const?override?{?return?false;?}????bool?eatenBy(const?Cat&)?const?override?{?return?false;?}
          ????bool?eatenBy(const?Lion&)?const?override?{?return?true;?}};


          使用方式如下:

          animal1.eat(animal2);


          OK,滿足需求。


          這里有幾個關(guān)鍵點:

          • 基類那里需要使用前置聲明,因為基類需要使用派生類的引用。

          • 這里產(chǎn)生了兩次多態(tài),一次是運行時多態(tài),另一次是編譯時多態(tài)。

          • 代碼邏輯清晰,沒有那么多if-else,擴展方便。

          這種模式叫雙分派設(shè)計模式,關(guān)鍵在于基于參數(shù)上的方法調(diào)用來確定結(jié)果。


          打完收工。


          瀏覽 29
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  99日韩视频 | 国产一区二区天堂 | 国产成人无码毛片 | 欧美视频中文字幕 | 一本大道久久无码精品一区二区三区 |