Home  >  Q&A  >  body text

关于C++中的dynamic cast的使用

C++ primer中看到这个dynamic cast, 有点搞不太懂. 这个dynamic cast的作用到底是干嘛? 如果说一个父类指针中实际指向一个子类的话, 如果用这个指针调用一个虚函数, 就算没有dynamic-cast也会发生动态绑定吧? 如果用这个指针调用一个子类独有的函数, 那么这里应该用static cast, 好像和dynamic cast 也没什么关系? 那就不懂了, dynamic cast到底有什么用...

按照1L的回复我写了如下代码 :

//p.h
class P{

};

//s.h
#include "p.h"

class S : public P{

};

//main.cpp
#include <iostream>
#include "s.h"

int main(){
    //std::shared_ptr<P> x(new S);
    //std::shared_ptr<S> y = std::dynamic_pointer_cast<S>(x);
    P* x = new S;
    S* y = dynamic_cast<S*>(x);
}

结果报错 :

main.cpp:8:12: error: 'P' is not polymorphic
    S* y = dynamic_cast<S*>(x);
           ^                ~
1 error generated.
阿神阿神2765 days ago611

reply all(7)I'll reply

  • 怪我咯

    怪我咯2017-04-17 14:26:28

    dynamic_cast is typically used for down-cast check. e.g.

    class Base{
    // .... 
    // Base must be polymorphic!!! (has virtual members)
    virtual void foo();
    
    };
    
    class Derive: public Base{
    virtual void foo() override {
    cout<<"Derive::foo()"<<endl;
    }
    
    void derive_only() {
    cout<<"this method only exists for derive type\n";
    }
    
    };
    Base* pDerive = new Derive();
    Derive* pd;
    if((pd = dynamic_cast<Derive*>(pDerive)){
    //downcast successful 
    pd->derive_only(); // prints "derive only method"
    }else{
    //the pDerive is not Derive type
    }
    

    reply
    0
  • 天蓬老师

    天蓬老师2017-04-17 14:26:28

    Thank you for the invitation.
    Someone has already answered it well before, so I won’t go into details about the usage of dynamic_cast here.

    Here we mainly talk about why dynamic_cast should be used. The previous answer is that it is safer.
    Also, if you need to convert between different base class pointers pointing to the same object, using dynamic_cast can ensure the correctness of the conversion.
    There is also a pointer of the base class type, which can point to objects of different subclasses. However, pointers of two subclass types cannot point to each other's objects. If you convert, an error will occur. At this time, you can use dynamic_cast to determine which subclass object the base class pointer points to at runtime.

    Give an example. http://ideone.com/oUgVpo

    #include <iostream>
    using namespace std;
    class A {
      public:
      virtual ~A(){}
      int a;
    };
    class B{
      public:
      virtual ~B(){}
      int b;
    };
    class AB : virtual public B,virtual public A {};
    int main()
    {
      AB *pab = new AB();
      A* pa = (A*)pab;    // AB先继承的B,所以pa指向的是后16个字节
      B* pb = (B*)pab;    // pb指向前16个字节
      cout<<"pab = "<<pab<<"\npa  = "<<pa<<"\npb  = "<<pb<<endl;    // 注意差值,包含了虚基类指针
    
      cout<<dynamic_cast<AB*>(pa)<<endl;    // 源类型是多态,可以转换
      // cout<<static_cast<AB*>(pa)<<endl;    // 不能转换,多态类型需要使用dynamic_cast来转换
      return 0;
    }

    reply
    0
  • 伊谢尔伦

    伊谢尔伦2017-04-17 14:26:28

    dynamic_cast has the function of type checking, and a bad_cast exception will be thrown if it fails. Safer than static_cast, static_cast is forced to transfer directly without any check

    reply
    0
  • 大家讲道理

    大家讲道理2017-04-17 14:26:28

    After repeated experiments, I found that I only need to add a virtual function to the parent class, or set the destructor to a virtual function, but I don’t know why this happens...

    reply
    0
  • PHP中文网

    PHP中文网2017-04-17 14:26:28

    The simplest example:

    class Father
    {
    public:
        virtual void func1() { std::cout << "Father" << std::endl; }
        virtual ~Father(){}
    };
    class Son :public Father
    {
    public:
        virtual void func1(){ std::cout << "Son1" << std::endl; }
        void func2(){ std::cout << "Son2" << std::endl; }
        virtual ~Son(){}
    };
    class Factory
    {
    private:
        Father* myFather;
    public:
        void setFun(Father* m_Father) { myFather = m_Father; }
        Father* getFun() { return myFather;};
    };
    
    int main()
    {
        Father *m_Father = new Father();
        Factory* m_Factory = new Factory();
        m_Factory->setFun(m_Father );
        m_Factory->getFun()->func1();
        dynamic_cast<Son*>(m_Factory->getFun())->func2();
        ///
        return 0;
    }

    reply
    0
  • ringa_lee

    ringa_lee2017-04-17 14:26:28

    http://stackoverflow.com/ques...

    reply
    0
  • 伊谢尔伦

    伊谢尔伦2017-04-17 14:26:28

    The dynamic_cast conversion is based on the type_info in front of the virtual table for conversion. Only classes containing virtual functions can use dynamic_cast.

    And the above type_info is generated by the compiler during compilation, so if type_info is not found during compilation, an error will be reported.

    reply
    0
  • Cancelreply