dynamic_cast是否检查查询对象的type_info对象,还是递归检查?

时间:2014-07-30 08:54:41

标签: c++ polymorphism vtable dynamic-cast typeinfo

我一直在阅读dynamic_cast如何工作,从我到目前为止收集的内容,它获取对象,获取vptr,转到vtable,在-1或0元素中,有一个指向一个type_info个对象。但是,从这一点来看,它有点模糊:

type_info对象是否包含(可能)执行转换所需的所有数据,或者运行时系统是否需要访问其他type_info对象?

我试图了解在dynamic_cast期间检查继承层次结构时访问了多少个不同的对象/ vtable和type_info对象。

编辑:编译方式MSVC或GCC

1 个答案:

答案 0 :(得分:0)

这是未指定的,取决于实施,但是 有关将指针转换为另一种类型的信息 层次结构,至少在涉及虚拟继承时, 取决于实际最派生的类;找到了 class是D,来自BC的信息帮助 在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;
}

各种数据元素的初始化允许您查看 不同类别(或其有效载荷)的位置 清楚。

特别注意B子对象的vptr在DB中是不同的。它指向的vtbl中的RTTI信息必须反映最派生的类。