Стоит ли ожидать, что указатели повышают и понижают в одиночном наследовании?

Предположим, у меня есть:

class Base {
public:
    virtual void Nothing() {}
};
class MiddleDerived : public Base {
    virtual void Nothing() {}
};
class Derived : public MiddleDerived {
    virtual void Nothing() {}
};

и мой код выглядит так:

Derived* object = new Derived();
Base* base = object; //implicit conversion here

void* derivedVoid = object;
void* baseVoid = base;

Должен ли я ожидать, что baseVoid == derivedVoid?

Я знаю, что большинство реализаций работают таким образом, но гарантировано ли это?

2 ответа

Я думаю, что часть стандарта, которая имеет дело с этим - §5.2.9 (13)

Который утверждает (в двух словах), что T* приведен к пустоте *, а затем обратно к T* должен ссылаться на тот же объект.

Однако нет никаких оговорок адрес Derived должен совпадать с адресом его Base,

Таким образом, мой ответ будет: "нет - код, который ожидает, что эта эквивалентность является плохо сформированной и не допускает неопределенного поведения".

То, что вы "должны ожидать", может отличаться от того, что гарантировано.

static_cast вверх или вниз по цепочке наследования может изменить адрес.

Канонический пример, где это происходит на практике, - это когда базовый класс является неполиморфным, а производный класс представляет некоторую виртуальную функцию, которая со многими компиляторами затем вводит указатель vtable в начале каждого производного объекта.

Другие вопросы по тегам