Reputation: 1532
#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();
}
Upvotes: 3
Views: 263
Reputation: 126787
You are not supposed to mess with non-POD types like that. In particular, the C++ standard says that memcpy
ing 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).
Upvotes: 4
Reputation: 2513
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()
Upvotes: 0
Reputation: 545558
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.
Upvotes: 3
Reputation: 17258
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!
Upvotes: 3
Reputation: 132994
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
Upvotes: 0
Reputation: 272467
Doing raw memory manipulation (such as memcpy
) on non-POD types invokes undefined behaviour. You shouldn't do it!
Upvotes: 9