8

In the last two lines of below program, static_cast<void*> and dynamic_cast<void *> behave differently. From what I understand, The result of a dynamic_cast<void*> always resolves to the address of the complete object. So it uses RTTI in some way. Could anyone explain how compilers uses RTTI to differentiate between the two.

#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;
}

Possible output: https://ideone.com/WoX5DI

28
1,2,3,4
0xbfcce604
1
0xbfcce618
0xbfcce618
0xbfcce604
manlio
  • 18,345
  • 14
  • 76
  • 126
claudius
  • 1,112
  • 1
  • 10
  • 23
  • 3
    Dynamic cast to `void*` works the same way as dynamic cast to derived class pointer. In the typical implementation it looks up the vptr of the object pointed to by the pointer and uses that to determine the type of the most derived object. The offset can then be calculated accordingly. – Brian Bi Apr 15 '14 at 05:25
  • @Brian That is impossible in the void* case –  Apr 15 '14 at 05:29
  • `dynamic_cast` - does it even make sense to do? Every code that does it should fail any decent review. – BЈовић Apr 15 '14 at 07:51
  • 1
    @BЈовић: `dynamic_cast` to `void *` is a dedicated, specific feature of `dynamic_cast` designed that way on purpose. I never used it in practice, but apparently someone thought it made practical sense. – AnT stands with Russia Apr 15 '14 at 07:53

1 Answers1

9

From 5.2.7 / 7:

If T is "pointer to cv void," then the result is a pointer to the most derived object pointed to by v. Otherwise, a run-time check is applied to see if the object pointed or referred to by v can be converted to the type pointed or referred to by T.

So using dynamic_cast<void*>(o) you get a pointer to the first byte of the most "derived" object (if o is polymorphic).

The code the compiler generates for dynamic_cast<void *>(...) is something like:

static_cast<void*>(dynamic_cast<most_derived_type *>(...))

This property is often used for serialization.

manlio
  • 18,345
  • 14
  • 76
  • 126