dynamic_cast与static_cast到void*的区别

8
在下面程序的最后两行中,static_cast<void*>dynamic_cast<void *>的行为不同。据我所知,dynamic_cast<void*>的结果始终解析为完整对象的地址。因此它以某种方式使用了RTTI。请问有人能解释编译器如何使用RTTI来区分这两者吗?
#include <iostream>
using namespace std;
class Top {
protected:
int x;
public:
    Top(int n) { x = n; }
    virtual ~Top() {} 
    friend ostream& operator<<(ostream& os, const Top& t) {
        return os << t.x;
    }
};
class Left : virtual public Top {
protected:
    int y;
public:
    Left(int m, int n) : Top(m) { y = n; }
};
class Right : virtual public Top {
protected:
    int z;
public:
    Right(int m, int n) : Top(m) { z = n; }
};
class Bottom : public Left, public Right {
    int w; 
public:
    Bottom(int i, int j, int k, int m): Top(i), Left(0, j), Right(0, k) { w = m; }
    friend ostream& operator<<(ostream& os, const Bottom& b) {
        return os << b.x << ',' << b.y << ',' << b.z<< ',' << b.w;
    }
};
int main() {
    Bottom b(1, 2, 3, 4);
    cout << sizeof b << endl;
    cout << b << endl;
    cout << static_cast<void*>(&b) << endl;
    Top* p = static_cast<Top*>(&b);
    cout << *p << endl;
    cout << p << endl;
    cout << static_cast<void*>(p) << endl;
    cout << dynamic_cast<void*>(p) << endl;
    return 0;
}

可能的输出: https://ideone.com/WoX5DI
28
1,2,3,4
0xbfcce604
1
0xbfcce618
0xbfcce618
0xbfcce604

3
将对象指针进行void*动态转换的方式与将其转换成派生类指针的方式相同。在典型的实现中,它会查找指针所指向的对象的虚函数表(vptr),并使用该表来确定最终派生对象的类型。然后可以相应地计算偏移量。 - Brian Bi
@Brian 在 void* 的情况下是不可能的。 - user2249683
dynamic_cast<void*> - 这有意义吗?任何使用它的代码都应该无法通过合理的审核。 - BЈовић
1
@BЈовић:dynamic_castvoid *dynamic_cast 的一个专门的、特定的功能,是有意设计成这样的。我在实践中从未使用过它,但显然有人认为它具有实际意义。 - AnT stands with Russia
1个回答

9
从5.2.7 / 7开始:
如果T为“指向cv void的指针”,则结果是指向v所指最派生对象的指针。否则,会应用运行时检查,以查看v所指或所引用对象是否可以转换为T所指或所引用的类型。
因此,如果o是多态的,则使用dynamic_cast(o)可以获得指向最“派生”对象的第一个字节的指针。
编译器为dynamic_cast(...)生成的代码类似于:
static_cast<void*>(dynamic_cast<most_derived_type *>(...))

这个属性通常用于序列化。


4
C++充满了惊喜。 - Danvil
这对于指针比较以建立对象标识尤其有用,特别是在存在(非“虚拟”)菱形继承时。 - Arne Vogel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接