Почему это не полиморфно? - PullRequest
3 голосов
/ 24 июня 2011
#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 ]

9 голосов
/ 24 июня 2011

Выполнение необработанных манипуляций с памятью (например, memcpy) на не POD типах вызывает неопределенное поведение .Ты не должен этого делать!

4 голосов
/ 24 июня 2011

Вы не должны связываться с не POD-типами.В частности, стандарт C ++ гласит, что memcpy использование не POD приводит к неопределенному поведению, которое, в вашем случае, показывает, что продолжает видеть a как тип A.

В вашемВ конкретном случае компилятор «знает», что и «статический тип», и «динамический тип» a равны A (поскольку его тип не может «законно» измениться - ваш трюк недопустим), поэтомувиртуальная диспетчеризация выполняется, но a.foo() вызывается напрямую (и ваш трюк с перезаписью vptr, таким образом, не действует).

3 голосов
/ 24 июня 2011

Потому что - зачем это?Компилятор видит, что a не является указателем или ссылкой, и поэтому не может вызывать ничего, кроме оригинальной реализации foo.Компилятор не заботится о том, чтобы сделать вызов виртуальным (потому что это излишне дорого).

Как сказал Оли, ваша байтовая копия вызывает неопределенное поведение.Все идет.

3 голосов
/ 24 июня 2011

Потому что вы действуете на всех без исключения гарантиях с memcpy, и вам повезло, что вы вообще себя ведете. Используйте оператор присваивания, как вы должны!

0 голосов
/ 24 июня 2011
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()
0 голосов
/ 24 июня 2011
memcpy(&a, &b, sizeof (b));
(&a)->foo();

Это неопределенное поведение . Это гарантированно работает только для POD -типов. Итак ... UB - это UB. Не нужно удивляться

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...