About dynamic cast and address of base and derived objects

前端 未结 4 1935
名媛妹妹
名媛妹妹 2021-01-22 11:10

I was reading through some of effective c++ and I realized I may be incorrect in my thinking along the way.

class A
{
    public:
    void laka()
    {
        c         


        
相关标签:
4条回答
  • 2021-01-22 11:11

    This is all compiler and implementation dependent. In your case a B is a A + something, so it sotres the A then the B specific members. so the address of &b and the one displayed by your dynamic_cast ought to be the same.

    0 讨论(0)
  • 2021-01-22 11:19

    Most implementations of inheritance put the first base class subobject at the beginning of the derived class, so you really need two base classes, both with data members, to be able to see this. Consider:

    #include <iostream>
    
    struct B1 { 
        int x; 
        virtual ~B1() { } 
    };
    
    struct B2 {
        int y;
        virtual ~B2() { }
    };
    
    struct D : B1, B2 { };
    
    int main() {
        D x;
        B1* b1_ptr = &x;
        B2* b2_ptr = &x;
        std::cout << "original address:     " << &x << "\n";
    
        std::cout << "b1_ptr:               " << b1_ptr << "\n";
        std::cout << "dynamic_cast b1_ptr:  " << dynamic_cast<void*>(b1_ptr) << "\n";
    
        std::cout << "b2_ptr:               " << b2_ptr << "\n";
        std::cout << "dynamic_cast b2_ptr:  " << dynamic_cast<void*>(b2_ptr) << "\n";
    }
    

    Example output (from my machine; your results will be similar):

    original address:     0030FB88
    b1_ptr:               0030FB88
    dynamic_cast b1_ptr:  0030FB88
    b2_ptr:               0030FB90
    dynamic_cast b2_ptr:  0030FB88
    

    This tells us that the B1 subobject of D is located at the beginning, so it has the same address as the D object of which it is a subobject.

    The B2 subobject is located at a different address, but when you use dynamic_cast<void*> on the pointer to the B2 subobject, it gives you the address of the D object of which it is a subobject.

    0 讨论(0)
  • 2021-01-22 11:22

    The book was correct, a dynamic_cast to cv-qualified void* converts the pointer to a pointer to the most derived object pointed to by the pointer that you supply, so you get the starting address of the derived object. Both your output statements should print the same address (assuming there isn't a specific std::ostream and B* overload for operator<<) as b is the most derived object.

    There is no reason the a base class subobject can't have the same starting address as a derived object and this is what often happens in many implementations, at least for the first base class subobject in a derived class.

    0 讨论(0)
  • 2021-01-22 11:22
    1. When I just output the address of the plain old &b above, is the address displayed the starting address of the derived object or the base object within b?

    You could say "yes", it's the starting address of the base object class A within b (which is the same as the starting address of the derived object b itself) ... but the derived object is not really a "separate" object from the base-object. The derived object is also not something that will necessarily start with a fixed offset from the base object, especially if it's a non-POD class (plain-old-data-type) with virtual functions since the first address of both the base and derived objects is a pointer to a v-table specific to either the base or derived object. So you can't really "slice" apart a derived object into a "base-object" and derived object, other than the fact that for most compiler instances, the derived objects non-static data members will come after an offset from the non-static data memebers of the base-object. But again, arbitrary "slicing" will cause issues with the v-table pointer, and also for non-POD classes, any private non-static member objects may be allocated in an "optimized" fashion that may make the memory layout between the base and derived objects something that is not exactly a clean "slice".

    0 讨论(0)
提交回复
热议问题