【问题标题】:What are some 'good use' examples of dynamic casting?动态转换有哪些“好用”的例子?
【发布时间】:2017-09-20 08:06:49
【问题描述】:

我们经常听到/读到应该避免动态转换。根据您的说法,我想知道它的“有用”示例是什么?

编辑:

是的,我知道that other thread:确实是在阅读那里的第一个答案时,我问了我的问题!

【问题讨论】:

  • 此问题的标题与描述不完全相符。

标签: c++ casting rtti dynamic-cast


【解决方案1】:

这个最近的帖子给出了一个例子,说明它在哪里派上用场。有一个基本的 Shape 类和派生自它的类 Circle 和 Rectangle。在测试相等性时,很明显 Circle 不能等于 Rectangle,尝试比较它们将是一场灾难。在遍历指向 Shapes 的指针集合时,dynamic_cast 会执行双重任务,告诉您形状是否具有可比性,并为您提供合适的对象来进行比较。

Vector iterator not dereferencable

【讨论】:

    【解决方案2】:

    这是我经常做的事情,它并不漂亮,但它简单实用。

    我经常使用实现接口的模板容器, 想象一下

    template<class T>
    class MyVector : public ContainerInterface
    ...
    

    ContainerInterface 有基本有用的东西,但仅此而已。如果我想要一个关于整数向量的特定算法而不暴露我的模板实现,那么在实现中接受接口对象并将其动态转换为 MyVector 很有用。示例:

    // function prototype (public API, in the header file)
    void ProcessVector( ContainerInterface& vecIfce );
    
    // function implementation (private, in the .cpp file)
    void ProcessVector( ContainerInterface& vecIfce)
    {
        MyVector<int>& vecInt = dynamic_cast<MyVector<int> >(vecIfce); 
        // the cast throws bad_cast in case of error but you could use a
        // more complex method to choose which low-level implementation
        // to use, basically rolling by hand your own polymorphism.
    
        // Process a vector of integers
        ...
    }
    

    我可以向 ContainerInterface 添加一个 Process() 方法,该方法将被多态解析,这将是一个更好的 OOP 方法,但我有时更喜欢这样做。当您拥有简单的容器、大量算法并且您希望隐藏您的实现时,dynamic_cast 提供了一个简单而丑陋的解决方案。

    您还可以查看双分派技术。

    HTH

    【讨论】:

      【解决方案3】:

      我目前的玩具项目使用了两次dynamic_cast;一次是为了解决 C++ 中缺少多重调度的问题(它是一种访问者风格的系统,可以使用多重调度而不是 dynamic_casts),一次是为了特殊情况下的特定子类型。

      在我看来,这两个都是可以接受的,尽管前者至少源于语言缺陷。事实上,我认为这可能是一种常见的情况;大多数 dynamic_casts(以及许多一般的“设计模式”)是针对特定语言缺陷的解决方法,而不是针对某些目标。

      【讨论】:

        【解决方案4】:

        当通过 C 接口向对象公开句柄时,它可以用于一点运行时类型安全。让所有公开的类都继承自一个公共基类。接受函数句柄时,首先转换为基类,然后动态转换为您期望的类。如果他们传入了一个无意义的句柄,当运行时找不到 rtti 时,你会得到一个异常。如果他们传入了错误类型的有效句柄,您将获得一个 NULL 指针并可以抛出您自己的异常。如果他们传递了正确的指针,你就可以走了。 这不是万无一失的,但它肯定比直接从句柄重新解释转换更好地捕捉对库的错误调用,然后等到当你传入错误的句柄时某些数据被神秘地破坏。

        【讨论】:

          【解决方案5】:

          如果使用 C# 中的扩展方法真的会很好。

          例如,假设我有一个对象列表,我想从中获取所有 id 的列表。我可以单步执行它们并将它们拉出来,但我想分割出那些代码以供重用。

          有点像

          List<myObject> myObjectList = getMyObjects();
          
          List<string> ids = myObjectList.PropertyList("id");
          

          会很酷,除非在扩展方法上你不知道传入的类型。

          所以

          public static List<string> PropertyList(this object objList, string propName) {
              var genList = (objList.GetType())objList;
          }
          

          会很棒。

          【讨论】:

            【解决方案6】:

            它非常有用,但是,在大多数情况下它有用:如果要完成工作,最简单的方法是进行 dynamic_cast,这往往不是坏的症状OO 设计,这反过来又会以不可预见的方式在未来导致麻烦。

            【讨论】:

              猜你喜欢
              • 2012-06-23
              • 2011-02-11
              • 1970-01-01
              • 2010-09-26
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2012-05-02
              • 1970-01-01
              相关资源
              最近更新 更多