RCX でシングルトンを実装するには
シングルトンオブジェクトを表現しようとして以下のようなコードを書いたところ、
MenuCommandBuilder & MenuCommandBuilder::instance() { static MenuCommandBuilder instance_; return instance_; }
以下のようにコンパイラに怒られました。
$ make /usr/local/crossgcc/h8300-hms/bin/h8300-hms-ld main.o Calibrator.o Console.o Men u.o Rcx.o Utility.o -T ../brickos/boot/brickOS.lds -relax -L../brickos/lib -lc - lmint -lfloat -lc++ --oformat coff-h8300 -Ttext 0xb000 -o lego.dc1 Menu.o(.text+0x406):Menu.cpp: undefined reference to `atexit' Menu.o(.text+0x406):Menu.cpp: undefined reference to `atexit' Menu.o(.text+0x406):Menu.cpp: undefined reference to `atexit' make: *** [lego.lx] Error 1
atexit がリンクできないことが原因。brickOS 側のソースを検索しても確かに実装されていない。試しに以下のコードをコンパイル・リンクすると通ります。
extern "C" void atexit() { }
今 RCX が手元になくて動作を確認できてないので動くかどうかはわかりません。
ちなみにメンバ関数内 static 変数はダメだけど、内部リンケージにすると大丈夫という。
static MenuCommandBuilder *instance_ = 0; MenuCommandBuilder & MenuCommandBuilder::instance() { if (!instance_) instance_ = new MenuCommandBuilder; return *instance_; }
さらに、static メンバ変数にしても大丈夫。
MenuCommandBuilder *MenuCommandBuilder::instance_ = 0; MenuCommandBuilder & MenuCommandBuilder::instance() { if (!instance_) instance_ = new MenuCommandBuilder; return *instance_; }
というわけで、シングルトンを実現するには
- 内部リンケージ変数をつかう
- static メンバ変数をつかう
あたりで実装するよ、という話。