Я читал вокруг, как dynamic_cast
работает и из того, что я до сих пор собирал, он получает объект, получает vptr, переходит в vtable и в элементе -1 или 0 есть указатель на type_info
объект. Однако с этого момента становится немного туманно:
Ли type_info
объект содержит все данные, необходимые (возможно) для приведения, или системе времени выполнения необходим доступ к другим объектам type_info?
Я пытаюсь понять, сколько различных объектов / vtables и объектов type_info обращаются при проверке иерархии наследования во время dynamic_cast
,
РЕДАКТИРОВАТЬ: компилятор MSVC или GCC
Это не указано и зависит от реализации, но
информация относительно преобразования указателя в другой тип в
иерархия, по крайней мере, когда задействовано виртуальное наследование,
зависеть от фактического наиболее производного класса; обнаружив, что
класс D
, информация от B
или же C
было бы не Помогите
найти фактический адрес A
в D
, Положение
A
часть в объекте будет отличаться в зависимости от наиболее
производный класс. Чтобы ясно это увидеть, создайте классы с данными
член и отображать разные адреса:
struct B
{
int b;
B() : b( 1 ) {}
virtual ~B() = default;
};
struct L : virtual public B
{
int l;
L() : l( 2 ) {}
};
struct R : virtual public B
{
int r;
R() : r( 3 ) {}
};
struct D: public L, public R
{
int d;
D() : d( 4 ) {}
};
struct E : public D
{
int e;
E() : e( 5 ) {}
};
template <typename T>
class HexDump
{
T const& myObj;
public:
HexDump( T const& obj ) : myObj( obj ) {}
friend std::ostream& operator<<( std::ostream& dest, HexDump const& obj )
{
dest.fill( '0' );
dest.setf( std::ios_base::hex, std::ios_base::basefield );
uint32_t const* p = reinterpret_cast<uint32_t const*>( &obj.myObj );
for ( int i = 0; i < sizeof(T) / sizeof(uint32_t); ++ i ) {
if ( i != 0 ) {
dest << ' ';
}
dest << std::setw( sizeof(uint32_t) * 2 ) << p[i];
}
return dest;
}
};
template <typename T>
HexDump<T>
hexDump( T const& obj )
{
return HexDump<T>( obj );
}
int
addrDiff( void const* lhs, void const* rhs )
{
return static_cast<char const*>( lhs ) - static_cast<char const*>( rhs );
}
int
main()
{
B* aD = new D;
B* anE = new E;
std::cout << "position of B in D: " << addrDiff( aD, dynamic_cast<D*>( aD ) ) << std::endl;
std::cout << "position of B in E: " << addrDiff( anE, dynamic_cast<E*>( anE ) ) << std::endl;
std::cout << "D: " << hexDump( *dynamic_cast<D*>( aD ) ) << std::endl;
std::cout << "E: " << hexDump( *dynamic_cast<E*>( anE ) ) << std::endl;
return 0;
}
Инициализация различных элементов данных позволяет увидеть
положение разных классов (или их полезных нагрузок)
ясно.
Обратите внимание, в частности, что VTPR из B
подобъект отличается в D
и в B
; информация RTTI в vtbl, на которую она указывает, должна отражать наиболее производный класс.