【问题标题】:How cast an interface object to a specific inherited object如何将接口对象强制转换为特定的继承对象
【发布时间】:2014-02-18 10:00:37
【问题描述】:

我有一个接口类:

Class IOperand
{
    virtual ~IOperand() {};

    virtual std::string  getType() const = 0;
}

我有几个像这样的继承类:

class Int8: public IOperand
{
    public:
      Int8(int8_t _value = 0);
      virtual ~Int8() {};
      virtual std::string getType() const;

      int8__t  getValue() const;

    private:
      int8_t _value
}

我在 IOperand 类型上使用指针,但我需要使用 getValue() 成员函数。 如何根据 getType() 的返回(返回包含目标子类名称的字符串)将 IOperand 类型对象转换为子类类型对象?

【问题讨论】:

    标签: c++ class c++11 casting type-conversion


    【解决方案1】:

    您要求将基类型转换为派生类型。通常这种类型的转换是糟糕设计的标志,因为在大多数情况下,基本类型应该提供一个虚拟方法来提供所需的操作。但是,在某些情况下,有必要强制转换为特定的类。实际上有两种方法可以做到这一点。

    未知的运行时类型
    如果您不知道该类型是否是 Int8,那么您需要一个多态向下转换。这是通过特殊的dynamic_cast 机制完成的,如下所示:

    IOperand* operand = // ...
    Int8* casted = dynamic_cast<Int8*>(operand);
    if (casted == nullptr) {
       // runtime type was not an Int8
       return;
    }
    // operate on casted object...
    

    已知的运行时类型
    如果您完全确定该类型是子类型,那么您可能想要使用static_cast。但是请注意,static_cast 不会像 dynamic_cast 那样进行检查。但是,执行static_cast 会明显更快,因为它不需要任何反射或遍历继承树。

    【讨论】:

      【解决方案2】:

      你应该使用 dynamic_cast: http://en.cppreference.com/w/cpp/language/dynamic_cast



      您可以比较字符串并编写 if/else 来转换指针。

      【讨论】:

        【解决方案3】:

        你可以这样做:

        IOperand *op = function_returning_ioperand_pointer();
        
        if (op->getType() == "Int8") {
            Int8 *int8_op = dynamic_cast<Int8*>(op);
            if (!int8_op) std::cerr << "Cast failed" << std::endl;
        }
        

        【讨论】:

          【解决方案4】:

          参见维基百科的Run-time type information article:

          /* A base class pointer can point to objects of any class which is derived 
           * from it. RTTI is useful to identify which type (derived class) of object is 
            * pointed to by a base class pointer.
            */
          
           #include <iostream>
          
           class Base
           {
           public:
               Base() { } 
               virtual ~Base() { } 
          
               virtual void hello() 
               {
                   std::cout << "in Base";
               }
           };
          
           class Derived : public Base
           {
           public:
               void hello() 
               {
                   std::cout << "in Derived";
               }
           };
          
           int main()
           {
               Base* basePointer = new Derived();
               Derived* derivedPointer = NULL;
          
               //To find whether basePointer is pointing to Derived type of object
               derivedPointer = dynamic_cast<Derived*>(basePointer);
          
               if (derivedPointer != NULL)
               {
                   std::cout << "basePointer is pointing to a Derived class object"; //Identified
               }
               else
               {
                   std::cout << "basePointer is NOT pointing to a Derived class object";
               }
          
               //Requires virtual destructor 
               delete basePointer;
               basePointer = NULL;
          
               return 0;
           }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2014-01-16
            • 1970-01-01
            • 2015-04-11
            • 2011-03-03
            • 2011-01-05
            • 1970-01-01
            相关资源
            最近更新 更多