2015-08-27 88 views
0

我有一個嚴重的if-else dynamic_cast做downcast並執行特定的子類方法,如下所示。 (我知道使用的dynamic_cast可以被認爲是一些錯誤的設計。)更改使用dynamic_cast鑄造參考相比鑄造指針

void cryout(const Animal* pAnimal) 
{ 
    if(!pAnimal){ return; } 
    ... 
    if (auto pCat = dynamic_cast<const Cat*>(pAnimal)) 
    { 
     pCat->meow(); 
    } 
    else if (auto pDog = dynamic_cast<const Dog*>(pAnimal)) 
    { 
     pDog->bark(); 
    } 
    else 
    { 
     std::cerr << "No such animal.\n" ; 
    } 
} 

然後我想改變讓通過引用傳遞參數不用擔心空指針的問題。

void cryout(const Animal& animal) 
{ 
    ... 
    try 
    { 
     auto& cat = dynamic_cast<const Cat&>(animal); 
     cat.meow(); 
    } 
    catch (std::bad_cast) 
    { 
     try 
     { 
      auto& dog = dynamic_cast<const Dog&>(animal); 
      dog.bark(); 
     } 
     catch (std::bad_cast) 
     { 
      std::cerr << "No such animal.\n"; 
     } 
    } 
} 

但這種改變涉及堆棧當非貓的動物對象傳入平倉。據我所知,棧展開可能會導致性能降級了很多。在我的情況下,這是通過參考的方法實踐嗎?

順便說一句,在正常工作流程中拋出「std :: bad_cast異常」並不奇怪嗎?

+1

爲什麼不只是'dynamic_cast (&動物)'? – paddy

+0

是否建議不要使用dynamic_cast (animla)? –

+1

@ChenOT不,如果你期望它經常失敗;例外情況應該只用於特殊情況 –

回答

0

鑑於小背景下,解決辦法是這樣的:

#include <iostream> 
#include <string> 

struct Animal 
{ 
    virtual ~Animal() {}  
}; 

struct Dog : Animal { 
    void bark() const { std::cout << "bark\n"; } 
}; 

struct Cat : Animal { 
    void meow() const { std::cout << "meow\n"; } 
}; 

void cryout(const Animal& pAnimal) 
{ 
    if (auto pCat = dynamic_cast<const Cat*>(&pAnimal)) 
    { 
     pCat->meow(); 
    } 
    else if (auto pDog = dynamic_cast<const Dog*>(&pAnimal)) 
    { 
     pDog->bark(); 
    } 
    else 
    { 
     std::cerr << "No such animal.\n" ; 
    } 
} 

int main() 
{ 
    Cat c; 
    cryout(c); 
    Dog d; 
    cryout(d); 
} 

但除非沒有選擇 - Animal應該在子類中重寫一個純虛函數cryout()。 ..