为什么不是这种多态?

时间:2011-06-24 13:24:25

标签: c++ polymorphism

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

6 个答案:

答案 0 :(得分:9)

non-POD类型上执行原始内存操作(例如memcpy)会调用未定义的行为。你不应该这样做!

答案 1 :(得分:4)

你不应该像那样混淆非POD类型。特别是,C ++标准说memcpy非POD导致未定义的行为,在您的情况下,显示为继续aA类型。

在您的特定情况下,编译器“知道”a的“静态类型”和“动态类型”都是A(因为其类型不能“合法地”更改 - 你的技巧是非法的,所以没有执行虚拟调度,但是直接调用a.foo()(因此你覆盖vptr的技巧没有效果)。

答案 2 :(得分:3)

因为你对memcpy的任何和所有保证都非常粗暴,并且很幸运能得到任何行为。按照你的意愿使用赋值运算符!

答案 3 :(得分:3)

因为 - 为什么要这样?编译器发现a不是指针或引用,因此除foo的原始实现之外不能调用任何内容。编译器不打扰使调用成为虚拟(因为这是不必要的昂贵)。

正如Oli所说,你的字节副本会引发未定义的行为。一切顺利。

答案 4 :(得分:0)

memcpy(&a, &b, sizeof (b));
(&a)->foo();

这是undefined behavior。这保证仅适用于POD - 类型。所以... UB是UB。不用惊讶

答案 5 :(得分:0)

A a;
    B b;
    memcpy(&a, &b, sizeof (b));

如果A有成员,您将在此代码中遇到访问冲突。 正确的方法是下一步:

A a;
B b;
A *c = &a;
c->foo(); //A::foo()
c = &b;
c->foo(); //B::foo()