テクマクマヤコン @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