Я столкнулся с проблемой, которую можно свести к следующему примеру:
#include "iostream"
struct A {
char a;
};
struct B : A {
virtual void f() = 0;
};
struct C : B {
void f() override {}
};
void f(A* fpa) {
std::cout << fpa << '\n' << reinterpret_cast<C*>(fpa) << std::endl;
}
int main() {
C c {};
A* pa {&c};
std::cout << &c << '\n' << pa << '\n' << reinterpret_cast<C*>(pa) << std::endl;
f(&c);
}
Ни pa
, ни fpa
не указывают на адрес c
, хотя оба они инициализируются с &c
. Все адреса, напечатанные после адреса &c
, смещаются на +8 (протестировано с g ++ и clang ++). Удаление A :: a или B :: f () и C :: f () или инициализация pa
и fpa
с помощью reinterpret_cast<A*>(&c)
вместо просто &c
исправляет адреса.
Но почему я должен это делать? Разве любой A*
не может содержать адрес для любого A
, B
или C
в этом случае, поскольку все наследование публикуется c? Почему значение изменяется неявно? И есть ли флаги предупреждений, которые я могу передать g ++ или clang ++, которые предупреждают о таком поведении?