Is it allowed to write an instance of Derived over an instance of Base?

后端 未结 4 2234
傲寒
傲寒 2020-12-11 22:35

Say, the code

    class Derived: public Base {....}

    Base* b_ptr = new( malloc(sizeof(Derived)) ) Base(1);
    b_ptr->f(2);
    Derived* d_ptr = new(b         


        
4条回答
  •  旧巷少年郎
    2020-12-11 23:15

    If you write this code more cleanly, it is easier to see what goes wrong:

    void * addr = std::malloc(LARGE_NUMBER);
    
    Base * b = new (addr) Base;
    b->foo();                    // no problem
    
    Derived * d = new (addr) Derived;
    d->bar();                    // also fine  (#1)
    
    b->foo();                    // Error! b no longer points to a Base!
    
    static_cast(d)->foo(); // OK
    b = d; b->foo();              // also OK
    

    The problem is that at the line marked (#1), b and d point to entirely separate, unrelated things, and since you overwrote the memory of the erstwhile object *b, b is in fact no longer valid at all.

    You may have some misguided thoughts about Base* and Derived* being convertible pointer types, but that has nothing to do with the present situation, and for the sake of this example, the two types may as well be entirely unrelated. It is only one the very last two lines that we use the fact that the Derived* is convertible to a Base*, when we perform the actual conversion. But note that this conversion is a genuine value conversion, and d is not the same pointer as static_cast(d) (at least as far as the language is concerned).

    Finally, let's clean up this mess:

    d->~Derived();
    std::free(addr);
    

    The opportunity to destroy the original *b has passed, so we may have leaked that.

提交回复
热议问题