Maison  >  Questions et réponses  >  le corps du texte

关于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.
阿神阿神2714 Il y a quelques jours583

répondre à tous(7)je répondrai

  • 怪我咯

    怪我咯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
    }
    

    répondre
    0
  • 天蓬老师

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

    谢邀。
    前面已经有人回答得很好了,这里就不再对dynamic_cast的用法多做赘述了。

    这里主要说一下为什么要用到dynamic_cast,前面也右回答,是更安全。
    还有,需要在指向同一个对象的不同基类指针之间的转换,使用dynamic_cast能够保证转换的正确性。
    还有就是基类类型的指针,指向可以不同子类对象。但是两个子类类型的指针,是不能指向对方的对象的。如果转换,是会出错的。这时候可以使用dynamic_cast在运行时判断基类指针指向的是哪一个子类的对象。

    举一个例子。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;
    }

    répondre
    0
  • 伊谢尔伦

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

    dynamic_cast具有类型检查的功能,失败会抛出bad_cast异常。比static_cast更安全,static_cast是不作任何检查直接强转的

    répondre
    0
  • 大家讲道理

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

    经过我反复试验, 发现只要在父类中加入一个虚函数, 或者把析构函数设为虚函数就可以了, 但是并不知道为什么会这样...

    répondre
    0
  • PHP中文网

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

    最简单的例子:

    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;
    }

    répondre
    0
  • ringa_lee

    ringa_lee2017-04-17 14:26:28

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

    répondre
    0
  • 伊谢尔伦

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

    dynamic_cast 转换的依据是虚表前面的 type_info 进行转换,只有包含虚函数的类才可以使用 dynamic_cast 。

    而且上述的 type_info 是在编译期由编译器生成,所以在编译的时候,如果没有找到 type_info,就会报错。

    répondre
    0
  • Annulerrépondre