【问题标题】:C++ casting programmatically : can it be done?以编程方式进行 C++ 铸造:可以做到吗?
【发布时间】:2008-10-28 12:26:37
【问题描述】:

假设我有一个 Base 类和几个 Derived 类。有什么方法可以将对象强制转换为派生类之一,而无需编写如下内容:


string typename = typeid(*object).name();
if(typename == "Derived1") {
   Derived1 *d1 = static_cast&lt Derived1*&gt(object);
}
else if(typename == "Derived2") {
   Derived2 *d2 = static_cast &lt Derived2*&gt(object);
}
...
else {
  ...
}

【问题讨论】:

    标签: c++ casting


    【解决方案1】:

    不要。

    阅读多态性。几乎所有“动态转换”情况都是难以实现的多态性示例。

    您在动态演员阵容中所做的任何决定都已经做出。只需将实际工作委托给子类即可。

    您遗漏了示例中最重要的部分。有用的、多态的工作。

    string typename = typeid(*object).name();
    if(typename == "Derived1") {
       Derived1 *d1 = static_cast< Derived1*>(object);
       d1->doSomethingUseful();
    }
    else if(typename == "Derived2") {
       Derived2 *d2 = static_cast < Derived2*>(object);
       d2->doSomethingUseful();
    }
    ...
    else {
      ...
    }
    

    如果每个子类都实现 doSomethingUseful,这一切就简单多了。并且是多态的。

    object->doSomethingUseful();
    

    【讨论】:

    • 这是一个小细节,但我想提一下。您的意思是 d1-> 和 d2-> 而不是 d1。和d2。 ,正确的?由于指针类型使用箭头运算符来访问成员函数。 :)
    【解决方案2】:

    您可以使用 dynamic_cast 并测试 NULL,但我会强烈考虑改用重构代码。

    如果您需要特定于子类的处理,Template Method 可能会有所帮助,但在不知道您要达到什么目的的情况下,这只是一个模糊的猜测。

    【讨论】:

      【解决方案3】:
      Derived1* d1 = dynamic_cast< Derived1* >(object);
      if (d1 == NULL)
      {
          Derived2* d2 = dynamic_cast< Derived2* >(object);
          //etc
      }
      

      我的智能指针类型有以下方法,模拟 C# 'is' 和 'as':

      template< class Y > bool is() const throw()
          {return !null() && dynamic_cast< Y* >(ptr) != NULL;}
      template< class Y > Y* as() const throw()
          {return null() ? NULL : dynamic_cast< Y* >(ptr);}
      

      【讨论】:

        【解决方案4】:

        您可以使用dynamic_cast 执行此操作,例如:

        if ( Derived1* d1 = dynamic_cast<Derived1*>(object) ) {
            // object points to a Derived1
            d1->foo();
        }
        else if ( Derived2* d2 = dynamic_cast<Derived2*>(object) ) {
            // object points to a Derived2
            d2->bar();
        }
        else {
            // etc.
        }
        

        但正如其他人所说,这样的代码可能表明设计不佳,您通常应该使用virtual functions 来实现多态行为。

        【讨论】:

          【解决方案5】:

          通常,这是一个糟糕设计的标志。为什么需要这样做?或许可以重新设计,这样就不需要了。

          【讨论】:

            【解决方案6】:

            你到底想完成什么? 根据我的经验,这样的事情是糟糕设计的标志。重新评估您的类层次结构,因为面向对象设计的目标是让此类事情变得不必要。

            【讨论】:

              【解决方案7】:

              您的示例不会移植,因为未指定 name() 的确切格式。您可以尝试连续使用dynamic_casts。如果您转换为错误的类型,Dynamic_cast 将返回一个空指针。但是,如果您正在做这样的类型切换,那么您的设计就有问题。

              【讨论】:

                【解决方案8】:

                我认为 dynamic_cast 是要走的路,但我并不特别认为这对于所有可能的情况都是一个糟糕的设计,因为要转换的对象可能是某些第三方模块提供的东西。假设对象是由应用程序作者不知道的插件创建的。并且该特定插件可能会创建 Derived1(作为旧版本)类型对象或 Derived2(作为新版本)类型对象。也许插件接口不是为特定版本而设计的,它只是创建对象,因此应用程序必须进行这种检查以确保正确的转换/执行。在此之后,我们可以安全地调用 object.doSomethingUsefulThatDoesNotExistInDerived1();

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2010-09-19
                  • 1970-01-01
                  • 1970-01-01
                  • 2017-12-30
                  • 2010-11-24
                  • 1970-01-01
                  • 2020-09-03
                  • 1970-01-01
                  相关资源
                  最近更新 更多