2015-08-27 90 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()。 ..