为什么dynamic_cast是邪恶的?在这种情况下我应该使用dynamic_cast吗?

时间:2013-08-26 08:00:59

标签: c++ rtti dynamic-cast

有人说the use of dynamic_cast often means bad design and dynamic_cast can be replaced by virtual functions

  1. 为什么使用dynamic_cast认为设计不好?
  2. 假设我有函数名func(Animal* animal, int animalType),func中的实现就像:

    bool func(Animal* animal, int animalType)
    {
      ...
      /* Animal is the base class of Bear, Panda, Fish ....
      dynamic_cast animal to real animals(Bear, Panda, Fish...) 
      according to animalType. Do some processing with this specific
      type of animal, using its additional information beyond base 
      class Animal. */
    }
    
  3. 这种情况是否正确使用dynamic_cast

3 个答案:

答案 0 :(得分:16)

这绝对是使用dynamic_cast的错误位置。你应该使用多态。每个Animal类都应该有一个virtual函数,比如process,在这里你应该只调用animal->process()

class Animal{
    virtual void Process() = 0;
}
class Cat:public Animal{
    void Process() {cout<<" I am a tiny cat";}
}
class Bear :public Animal{
    void Process(){cout<<"I am a big bear";
}

void func(Animal* animal){
    if(animal != NULL) animal -> Process();
}

其他问题。

什么是animal是一只狗,但是由于一只虫animal_type说它是一只猫?

有时需要static_cast,如果可能,请使用它而不是动态强制转换。动态强制转换具有静态强制转换所不具备的额外性能成本。为此,您需要确保知道正在进入的类型,因为static_cast更不安全。

P.S。至少,animal_type应该是Animal的成员。

答案 1 :(得分:4)

理论上,永远不需要进行压铸。相反,您应该调整基类以包含必要的virtual方法。

在实践中,您会遇到第三方库等问题。在这种情况下,修改基类不是一个选项,因此您可能被迫使用dynamic_cast ...

回到你的例子:

class Animal {
public:
    // starts moving toward `p`,
    // throws a `Unreachable` exception if `p` cannot be reached at the moment.
    virtual void moveToward(Point const& p) = 0;
}; // class Animal

然后:

bool move(Animal& animal, Point const& p) {
    try {
        animal.moveToward(p);
        return true;
    } catch (Unreachable const& e) {
        LOG(animal.id() << " cannot reach " << p << ": " << e.what());
    }

    return false;
} // move

答案 2 :(得分:0)

当您使用向下转换时,dynamic_cast很好,因为它限制您向下转换为无关类型。请参阅this