コンストラクタ/デストラクタ中での仮想関数の呼び出し

本日の_| ̄|○な失敗。
Luaのラッパクラスを作ろうと思い、LuaStateとそこから派生したLuaThreadというクラスを作った。LuaStateではデストラクタ中で後片付け関数close()を呼び出す。Luaのthreadに対してlua_closeを呼ぶと落ちるのでLuaThreadではこのclose()をオーバーライドして、何もしない関数にさせたい。

// LuaのVMを扱う
class LuaState {
...
 ~LuaState() { close(); }

 virtual void close() { lua_close(L); }
};

// Luaのスレッドを扱う。LuaStateを継承する
class LuaThread : public LuaState {
...
  // LuaThreadではlua_close()をしてはいけないので何もしない関数にする
 virtual void close() { /* なにもしない */} 
}

ところがこのクラスを実行して、LuaThreadのデストラクタが呼び出されると落ちてしまう。理由はLuaStateのデストラクタ中で呼び出されるclose()が、何故かオーバーライドされたclose()のほうへ飛んで行かず、オーバーライド前のclose()に向かってしまうため。
何故?ちゃんとvirtual指定はしてあるし、問題はないはず・・・試しにクラス外や、メンバ関数の中から呼び出してやると、きちんとオーバーライドされた関数に飛んでいった。
ひょっとしてコンストラクタ/デストラクタ中で仮想関数の呼び出しは正しい結果にならないのか?疑問に思ってググってみると、発見(http://www.s34.co.jp/cpptechdoc/article/sizeof/index.html)。これは知らないと絶対ハマるポイントだわ。気づけてよかったと思うべきか、今まで知らなかったことを嘆くべきか。
というわけで、メンバ変数にスレッドかどうかのフラグを持たせてそこでlua_closeを呼ぶか呼ばないか判断させるようにした。カコワルイけど仕方が無い。
っていうか、LuaではStateもThreadもほぼ等質なものとして扱えて、Stateでも普通にyield()やresume()が呼び出せるので、わざわざLuaThreadなんてクラスを派生させる必要は無かったことに気づいた_| ̄|○