Qian
Qian

Reputation: 1532

Why isn't this polymorphic?

#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

Answers (6)

Matteo Italia
Matteo Italia

Reputation: 126787

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).

Upvotes: 4

zabulus
zabulus

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

Konrad Rudolph
Konrad Rudolph

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

Pontus Gagge
Pontus Gagge

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

Armen Tsirunyan
Armen Tsirunyan

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

Oliver Charlesworth
Oliver Charlesworth

Reputation: 272467

Doing raw memory manipulation (such as memcpy) on non-POD types invokes undefined behaviour. You shouldn't do it!

Upvotes: 9

Related Questions