#include <cstdio>
#include <cstring>
class A
{
public:
virtual void foo()
{
puts("A");
}
};
class B : public A
{
public:
void foo()
{开发者_StackOverflow中文版
puts("B");
}
};
int main()
{
A a;
B b;
memcpy(&a, &b, sizeof (b));
(&a)->foo();
}
Doing raw memory manipulation (such as memcpy
) on non-POD types invokes undefined behaviour. You shouldn't do it!
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).
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!
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.
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
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()
精彩评论