読者です 読者をやめる 読者になる 読者になる

本当にあった怖い話

c/c++
#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++では罠だったりするところが恐ろしい。