简体   繁体   English

`dynamic_cast`从Base到Derived

[英]`dynamic_cast` from Base to Derived

Yes, I know that downcast using dynamic_cast can't compile if the Base is not polymorphic, but my problem is not about this. 是的,我知道如果Base不是多态的,使用dynamic_cast downcast无法编译,但我的问题与此无关。

class Base {
    public:
        virtual void bar()
        {
            cout << "bar\n";
        }
};

class Derived: public Base {
    public:
        void foo()
        {
            cout << "foo\n";
        }
};

int main()
{
    Base *pb;
    Derived *pd;

    pb = new Derived;  //Base* points to a Derived object
    pd = dynamic_cast<Derived*>(pb); 
    pd->foo();  //outputs foo

    pb = new Base;  //Base* points to a Base object
    pd = dynamic_cast<Derived*>(pb);  
    pd->foo();  //outputs foo, too. Why?
}

I thought when pb = new Derived; pb = new Derived; , pb actually points to a Derived object lies in heap. pb实际上指向一个Derived对象位于堆中。 After pd = dynamic_cast<Derived*>(pb); pd = dynamic_cast<Derived*>(pb); , pd also points to that Derived object, so pd->foo() should be OK. pd也指向Derived对象,所以pd->foo()应该没问题。

But when pb = new Base; 但是当pb = new Base; , what pb points to is a Base object in heap, then after pd = dynamic_cast<Derived*>(pb); pb指向的是堆中的Base对象,然后是pd = dynamic_cast<Derived*>(pb); , how could pd->foo() works? pd->foo()怎么样? Did dynamic_cast turn the Base object in heap into a Derived object? dynamic_cast是否将堆中的Base对象转换为Derived对象?

In C++, each instance of a class has its own version of datatypes, but all classes share the same function in memory (other than for inline functions). 在C ++中,类的每个实例都有自己的数据类型版本,但所有类在内存中共享相同的函数(除了内联函数)。 In your case, when you say something like: 在你的情况下,当你说的话:

pd->foo();

You are essentially calling Derived::foo , which is a function in memory and the compiler knows where it is. 你本质上是调用Derived::foo ,它是内存中的一个函数,编译器知道它在哪里。 The thing is, it is not dependent on pd at all. 问题是,它完全不依赖于pd However, if you had something like this: 但是,如果你有这样的事情:

class Derived : public Base {
    private:
        int a;

    public:
        Derived() { a = 100; }

        void foo() {
            std::cout<<a<<std::endl;
        }
 };

Then, pd->foo() will cause a Segmentation fault. 然后, pd->foo()将导致分段错误。 Here, your dynamic cast has failed and when Derived::foo is called, it is passed 0 as the this object. 这里,您的动态强制转换失败,当调用Derived::foo时,它将作为this对象传递0 It was fine in the previous case, as the this object was never used. 在前一种情况下很好,因为this对象从未使用过。 However, in the second case, it is used and hence, causes a Segmentation fault. 但是,在第二种情况下,它被使用,因此导致分段错误。

In your foo you don't access this , which in this case should be NULL . 在你的foo你不能访问this ,在这种情况下应该为NULL That is what dynamic_cast returns when the cast cannot be done. 这就是当无法完成dynamic_castdynamic_cast返回的内容。

Basically you're in the "undefined behavior" area here. 基本上你在这里的“未定义行为”区域。

You're running into undefined behavior. 您遇到了未定义的行为。 You should check the return type of dynamic_cast . 您应该检查dynamic_cast的返回类型。

pd = dynamic_cast<Derived*>(pb);  

This returns null, and you call a function on a NULL pointer. 这将返回null,并在NULL指针上调用函数。 Anything can happen. 任何事情都可能发生。

Please always prefer to check whether the cast is successful before trying to use it. 在尝试使用之前,请务必先检查演员表是否成功。 I guess its the advantage of using casting. 我猜它是使用铸造的优势。 You can check whether its successful or not. 你可以检查一下是否成功。

pd = dynamic_cast<Derived*>(pb);  
if(pd!=NULL)
  pd->foo();

If the cast fails pd has value NULL. 如果转换失败,则pd值为NULL。 Do not use pd unless you are sure it has a value. 除非您确定它具有值,否则请勿使用pd and then only de reference it 然后只引用它

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM