#include <cstdio>
#include <cstring>
class A
{
public:
    virtual void foo()
    {
        puts("A");
    }
};
class B : public A
{
public:
    void foo()
    {
        puts("B");
    }
};
int main()
{
    A a;
    B b;
    memcpy(&a, &b, sizeof (b));
    (&a)->foo();
}
- 
                    3You know you're blowing the stack to smithereens should `B` ever be bigger than `A`? – Xeo Jun 24 '11 at 13:28
- 
                    2This is UB, but if you were trying to figure out if how hard you can blow your own foot, try with an extra level of indirection: pass the modified `A` object to a function like: `void call( A& x ) { x.foo(); }`, since it is UB you might get anything at all, even `B` being printed... or a crash now or in production code, or... I don't believe in demons but *nasal demons*, those are real! – David Rodríguez - dribeas Jun 24 '11 at 13:35
- 
                    Undefined behavior explains everything. – Qian Jun 24 '11 at 13:51
- 
                    This is almost more C than C++. Yes, there are classes, but cstdio and cstring? Why not use the C++ library? – kiswa Jun 24 '11 at 15:42
6 Answers
Doing raw memory manipulation (such as memcpy) on non-POD types invokes undefined behaviour.  You shouldn't do it!
 
    
    - 267,707
- 33
- 569
- 680
- 
                    (And, almost by extension, because there's _more to an object_ than the bytes that you can physically `memcpy`.) – Lightness Races in Orbit Jun 24 '11 at 13:28
- 
                    1@Tomalak: So is `sizeof(b)` not guaranteed to encapsulate *everything* related to the storage of `b`? (Genuine question.) – Oliver Charlesworth Jun 24 '11 at 13:30
- 
                    @Oli Charlesworth: it encapsulates everything not indirectly referenced. – Matthieu M. Jun 24 '11 at 13:43
- 
                    @Oli: Good question. I'm wondering whether the bytes under storage are guaranteed to encapsulate all the semantic information of the object. Consider the fact of the object's type, for starters. – Lightness Races in Orbit Jun 24 '11 at 13:46
- 
                    My saying: The size of a `struct` or `class` *may not* equal the sum of the size of the members. – Thomas Matthews Jun 24 '11 at 20:07
You are not supposed to mess with non-POD types like that. In particular, the C++ standard says that memcpying non-PODs results in undefined behavior, which, in your case, shows as continuing to see a as being of type A.
In your particular case, the compiler "knows" that the both the "static type" and the "dynamic type" of a is A (since its type can't "legally" change - your trick is illegal), so no virtual dispatch is performed, but a.foo() is called directly (and your trick of overwriting the vptr thus has no effect).
 
    
    - 129,499
- 52
- 291
- 397
 
    
    - 123,740
- 17
- 206
- 299
Because you're riding roughshod over any and all guarantees with your memcpy, and are lucky to get any behaviour at all. Use the assignment operator as you're supposed to!
 
    
    - 17,166
- 1
- 38
- 51
- 
                    Actually, the assignment operator wouldn't help here. But at least the result would be well-defined. – Oliver Charlesworth Jun 24 '11 at 13:27
- 
                    
Because – why should it? The compiler sees that a isn’t a pointer or reference and therefore cannot call anything but the original implementation of foo. The compiler doesn’t bother to make the call virtual (because that is needlessly expensive).
As Oli said, your byte copy provokes undefined behaviour. Anything goes.
 
    
    - 530,221
- 131
- 937
- 1,214
memcpy(&a, &b, sizeof (b));
(&a)->foo();
This is undefined behavior. This is guaranteed to work only for POD-types. So... UB is UB. No need to be surprised
 
    
    - 1
- 1
 
    
    - 130,161
- 59
- 324
- 434
A a;
    B b;
    memcpy(&a, &b, sizeof (b));
You will have an access violation in this code if A would have an members. Right way is next:
A a;
B b;
A *c = &a;
c->foo(); //A::foo()
c = &b;
c->foo(); //B::foo()
 
    
    - 2,373
- 3
- 15
- 27
 
    