実行時に所属クラスを変える話の続き。前回は 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