C ++ dynamic_cast - polymorphic requirement and downgrade

In the following code, when constructing objin case 1, we also construct a class object derived, but its member functions are not available for obj. Thus, while downcasting (i.e., in Case 2), using objas a source, we have already built derivedin it. Why objshould be polymorphic?

If I embarrassed you with my description above, why objshouldn’t it be polymorphic when increasing, but with a downconversion it should be polymorphic when using dynamic_cast?

class base
{
public:
    base()
    {
        cout<< " \n base constructor \n";
    }
};

class derived : public base
{
public:
    derived()
    {
        cout << " \n derived constructor \n";
    }
};

base *obj = dynamic_cast<base*> (new derived); // case 1: explicitly upcasting
derived *OBJ = dynamic_cast<derived*> (obj);   // case 2: error
+9
source share
4 answers

From 5.2.7 / 1 [expr.dynamic.cast]:

dynamic_cast<T>(v) v .

[...]

T " cv1 B", v " cv2 D", , B D, B D, v.

[...]

, v .

, , , :

struct B {};
struct D : B {};
void foo(D* dp)
{
    B* bp = dynamic_cast<B*>(dp); // equivalent to B* bp = dp;
}
+6

dynamic_cast, . , dynamic_cast - , , , vtable . vtable, .

- .

Upcasting (.. ) , , . , downcasting.

+16

dynamic_cast

  • . ,
  • . , :: bad_cast.
  • static_cast, , .

Dynamic_cast ( ) .

0
B* b = new D();
D* d = dynamic_cast<D*>(b);

, , vtable b vtable D . , b , nullptr. , , : -

class car
{
    public:
    virtual void drive()
    {
         std::cout <<"car"<<std::endl;
    }
};
class toyota: public car
{
    public:
    virtual void drive()
    {
        std::cout <<"toyota"<<std::endl;
    }
};

class honda: public car
{
    public:
        virtual void drive()
    {
        std::cout <<"honda"<<std::endl;
    }
};

template <typename Tderived>
Tderived* dynamicCast(void* pBase)
{
    //compare the vptr of the class pointed by pBase with a temporary Tderived class. 
    //If vptr of pBase and vptr of Tderived() are pointing to the same vtable 
    //then it can be safely deduced that pBase is indeed pointing to an instance of Tderived
    if (*(int**)pBase == *(int**)&Tderived())
    {
        return (Tderived*)pBase;
    }
    else
    {
        return nullptr;
    }
}


int main()
{
    car* pCar;
    honda hondaCar;
    toyota toyotaCar;

    pCar = &toyotaCar;

    honda* pHonda = dynamicCast<honda>(pCar);
    if (nullptr != pHonda)
    {
        pHonda->drive();
    }
    else
    {
        toyota* pToyota = dynamicCast<toyota>(pCar);
        if (nullptr != pToyota)
        {
            pToyota->drive();
        }
    }
}

, , , pCar honda toyota. , dynamic_cast, ++ vtables.

0

All Articles