テクマクマヤコン @C++

実行時に所属クラスを変える話の続き。前回は Objective-C だったけど今度は C++ でもやっておく。

http://d.hatena.ne.jp/shinichiro_h/20051231#1135964893

結局仮想関数テーブルを変えるだけなのでやることは一緒。

    void become(const Base& o) {
        *(void**)this = *(void**)&o;
    }

この時 const Base& o に渡す引数をあらかじめ sampleRight, sampleLeft として用意してるのがダサいです。消したきゃ _ZTV4Left + 8 と _ZTV5Right + 8 とかを使えば良さげ。

次回は気が向いたら C++ でポージング。

以下コードと実行結果。

#include <typeinfo>
#include <stdio.h>

using namespace std;

struct Base {
    Base() : x(0) {}
    virtual ~Base() {}
    virtual void move() = 0;
    int x;

    void become(const Base& o) {
        *(void**)this = *(void**)&o;
    }
};

struct Right : public Base {
    virtual void move();
};

struct Left : public Base {
    virtual void move();
};

static Right sampleRight;
static Left sampleLeft;

void Right::move() {
    x++;
    if (x > 2) {
        become(sampleLeft);
    }
}

void Left::move() {
    x--;
    if (x <= 0) {
        become(sampleRight);
    }
}

void f(Base* o) {
    for (int i = 0; i < 10; i++) {
        o->move();
        printf("i=%d x=%d class=%s\n", i, o->x, typeid(*o).name());
    }
}

int main() {
    Base* o = new Right;
    f(o);
}
i@u ~/test> g++ -g become.cc
i@u ~/test> ./a.out
i=0 x=1 class=5Right
i=1 x=2 class=5Right
i=2 x=3 class=4Left
i=3 x=2 class=4Left
i=4 x=1 class=4Left
i=5 x=0 class=5Right
i=6 x=1 class=5Right
i=7 x=2 class=5Right
i=8 x=3 class=4Left
i=9 x=2 class=4Left
なにかあれば下記メールアドレスへ。
shinichiro.hamaji _at_ gmail.com
shinichiro.h