本当にあった怖い話
#include <iostream> using namespace std; class Base { public: Base () : value_(0) {} Base (int value) : value_(value) {} virtual ~Base (){} virtual char* getName() const=0; int getValue() { return value_; } private: int value_; }; class Derived : public Base { public: Derived () : Base(1) {} virtual ~Derived (){} char* getName() const { return "Derived"; } }; class Foo : public Base { public: Foo () : Base(2) {} virtual ~Foo (){} char* getName() const { return "Foo"; } }; int main() { Base* d = new Derived(); Base* f = new Foo(); cout << d->getName() << d->getValue() << endl; cout << f->getName() << f->getValue() << endl; //!!!!!!!!!! memcpy(d, f, sizeof(Base)); cout << d->getName() << d->getValue() << endl; cout << f->getName() << f->getValue() << endl; delete f; delete d; return 0; }
Derived1
Foo2
Foo2
Foo2
ぬあ
仮想関数がおかしくなりやがった……、
というのもmemcpyが暗黙のvptr(仮想関数テーブルvtblを指し示すポインタ)を書き換えたからだけれども、
C++を書き始めた人などが気付かずにソースを書いているとこんな事が起きる。
質が悪いのは発覚しづらいソースになりがちだということ。
(memcpyがnew直後に表れる事が少ないだろうということ)
Cの常識的にはmemcpyでstructの複製を行うほうが良いのだろうけれど、
C++では罠だったりするところが恐ろしい。