实际使用dynamic_cast?

cex*_*rer 49 c++ casting rtti

我有一个关于dynamic_cast运算符的非常简单的问题.我知道这用于运行时类型识别,即在运行时了解对象类型.但是根据您的编程经验,您能否提供一个真实场景,您必须使用此运算符?没有使用它有什么困难?

Bjo*_*rnD 49

玩具示例

诺亚方舟将作为不同类型动物的容器.由于方舟本身并没有在意猴子,企鹅,和蚊子之间的区别,你定义一个类Animal,派生类Monkey,Penguin以及Mosquito由它,他们每个人存储为一个Animal在方舟.

一旦洪水结束,诺亚想要将动物分布在地球上,并将它们分配到它们所属的地方,因此需要更多关于存放在他的方舟中的通用动物的知识.作为一个例子,他现在可以尝试将dynamic_cast<>每只动物设置为a Penguin,以便找出哪些动物是企鹅在南极释放,哪些不是.

真实的例子

我们实现了一个事件监视框架,其中应用程序将运行时生成的事件存储在列表中.事件监视器会去通过这个列表,并检查他们有兴趣在这些特定的事件.事件类型是操作系统级的东西,如SYSCALL,FUNCTIONCALLINTERRUPT.

在这里,我们将所有特定事件存储在一个通用的Event实例列表中.然后,监视器将遍历此列表并将dynamic_cast<>他们看到的事件迭代到他们感兴趣的那些类型.所有其他(引发异常的那些)将被忽略.

问题:为什么不能为每种事件类型单独列出一个列表?

:您可以这样做,但它会使系统扩展新事件以及新监视器(聚合多个事件类型)更难,因为每个人都需要知道要检查的相应列表.

  • 他是否[ark](http://en.wikipedia.org/wiki/Noah%27s_Ark)之后建立了[arch](http://en.wikipedia.org/wiki/Arch)? (9认同)
  • 我喜欢玩具示例:) +1 (4认同)
  • 很棒的答案!+1! (2认同)

Ker*_* SB 10

一个典型的用例是访问者模式:

struct Element
{
    virtual ~Element() { }

    void accept(Visitor & v)
    {
        v.visit(this);
    }
};

struct Visitor
{
    virtual void visit(Element * e) = 0;
    virtual ~Visitor() { }
};


struct RedElement : Element { };
struct BlueElement : Element { };
struct FifthElement : Element { };


struct MyVisitor : Visitor
{
    virtual void visit(Element * e)
    {
        if (RedElement * p = dynamic_cast<RedElement*>(e))
        {
             // do things specific to Red
        }
        else if (BlueElement * p = dynamic_cast<BlueElement*>(e))
        {
             // do things specific to Blue
        }
        else
        {
             // error: visitor doesn't know what to do with this element
        }
    }
};
Run Code Online (Sandbox Code Playgroud)

现在,如果你有一些Element & e;,你可以MyVisitor v;说和说e.accept(v).

关键设计功能是,如果您修改Element层次结构,则只需编辑访问者.该模式仍然相当复杂,只有在您拥有非常稳定的类层次结构时才推荐使用Element.

  • 糟糕,通过重载`visit`方法来接受各种`Element`派生词,你可以完全避免使用`dynamic_cast`.我认为这是访问者模式的主要好处(`Element`对象向访问者展示了他们的具体类型). (7认同)
  • @ w00te也许,也许不是.但我绝对会避免在每个访问者中重复`dynamic_cast` switch语句,如果可能的话(DRY).我的主要观点是,我不同意"动态演员的典型用例是访客模式"的说法. (5认同)
  • 是的,这就是为什么`accept`通常在每个派生的`Element`类(或CRTP)中实现的原因.这样,`this`的类型在编译时就知道了. (4认同)
  • @AndrewDurward:重载解析是静态发生的.动态转换动态发生.我不认为他们解决了同样的问题.你的方法需要为每个派生自`Element`的类添加代码,非?无论如何,肯定有其他方式来实现访问者,但它是动态强制转换有用的好例子. (2认同)