代码之家  ›  专栏  ›  技术社区  ›  Vignesh Gunasekaran

如何一般地从void*指针动态转换?

  •  5
  • Vignesh Gunasekaran  · 技术社区  · 7 年前
    class BASE {
    public:
        virtual ~BASE() {}
        void lamp() {
            cout << "\nBASE CLASS";
        }
    };
    
    class DERIVED : public BASE {
    public:
        void fun();
    };
    
    void DERIVED::fun() {
        cout << "\nDERIVED CLASS!";
    }
    
    int main() {
    
        BASE * pbase = new DERIVED; //BASE CLASS POINTER
        void * vbase = pbase;       //VOID POINTER TAKING BASE POINTER 
        DERIVED * pder;             //DERIVED CLASS POINTER
    
        //pder = static_cast<DERIVED *>(vbase);  //THIS WORKS
        pder = dynamic_cast<DERIVED *>(vbase);   //THIS DOESN'T
        pder->lamp();
        pder->fun();
    
        return 0;
    }
    

    每当我尝试动态投射 void*

    我搜索了StackOverflow并遵循建议,在基类中实现了一个虚拟函数以避免错误。我做错了什么? 这有可能吗?

    我的总体意图是使用 无效*

    例如:

    void dynamicCast(void * vptr)
    {
        BASE * pbase = new DERIVED;
        DERIVED * pder;
    
        pder = dynamic_cast<DERIVED *>(vbase);
    }
    

    我应该能够将任何类型的指针传递给 dynamicCast 函数,并应将其转换为派生类指针。

    4 回复  |  直到 7 年前
        1
  •  4
  •   Picaud Vincent    7 年前

    我认为存在设计或/和理解问题

    如前所述,你不能 dynamic_cast void* .

    动态_投射 需要一些 运行时类型信息(RTTI) this link 无效*

    该信息被创建并绑定到至少具有一个 虚拟方法 没有

    struct A
    {
    };
    
    struct B : A
    {
    };
    
    int main()
    {
      B  b;
      A *a = &b;
    
      dynamic_cast<B *>(a);  // YOUR COMPILE TIME ERROR
    }
    

    this is generally a good thing

    struct A
    {
       virtual ~A() = default;
    };
    
    struct B : A
    {
    };
    
    int main()
    {
      B  b;
      A *a = &b;
    
      dynamic_cast<B *>(a);  // OK
    }
    

    还要注意的是 动态_投射 允许您检查转换是否合法。

    例如,我们可以添加一个 C 分类和检查:

    struct C 
    {
    };
    
    int main()
    {
      B  b;
      A *a = &b;
    
      assert(dynamic_cast<B *>(a)!=nullptr); // OK
      assert(dynamic_cast<C *>(a)==nullptr); // OK can not cast A to C 
    }
    

    这种

    assert(dynamic_cast<B *>(a)!=nullptr);
    B* b=static_cast<B*>(a);
    

    在调试模式下,您将使用 -DNDEBUG assert 您将只使用 static_cast

        2
  •  2
  •   Pete Becker    7 年前

    将指向对象类型的指针转换为指向void的指针时 只有 无效指针的有效转换为 返回其原始类型 . 你不能使用 dynamic_cast void 因为 不是多态类型,因此使用 static_cast . 这样地:

    BASE *pbase = new DERIVED;
    void *vbase = pbase; // Ok; implicit conversion to void*
    BASE *pbase1 = static_cast<BASE*>(vbase); // the cast is required
    

    一旦你找到了指向 BASE ,当然,您可以使用 要将其转换为指向派生类型的指针,请执行以下操作:

    DERIVED *pder = dynamic_cast<DERIVED*>(pbase1);
    
        3
  •  1
  •   fefe    7 年前

    dynamic_cast void * .

    根据规范 dynamic_cast<T>(v)

    如果T是指针类型,则v应为的PR值 ,结果是T型PR值。。。

    您应该做的是让您的所有类都派生自同一个多态基类(至少有一个虚拟函数) BASE BASE * 而不是

        4
  •  1
  •   Geoduck    7 年前

    您的通用链接列表应如下所示:

    class Node
    {
        Node* next;
        void* vdata;
    }
    

    这是唯一严格要求的数据结构,但您可能需要一个循环列表,或一个跟踪列表末尾的基节点,或一个双链接列表。