基本クラスのポインターでメンバー関数 (ポインター) を呼び出すことは「安全」(および/または移植可能) ですが、指されているオブジェクトはインスタンスの異なる派生クラスです。メンバー関数は、派生クラスのメンバー変数または関数にはアクセスしません。
/* Shortened example of what happens in the client code and library */
class Base { /* ... */ }
class DerivedA : public Base {
/* ... */
public: void doSomethingA(float dt);
}
void DerivedA::doSomethingA(float dt) {
/* Does not access members. Conventionally calls/accesses statics */
cout << "dt(" << dt << ")";
}
class DerivedB : public Base { /* ... */ }
typedef void (Base::*SEL_SCHEDULE)(float);
SEL_SCHEDULE pCallback = (SEL_SCHEDULE)(&DerivedA::doSomethingA);
DerivedB db = new DerivedB();
Base *b = &db;
/* pCallback and b are saved in a list elsewhere (a scheduler) which calls */
(b->*pCallback)(0.f);
これは(MSVC/Debug モードで) 実行時に問題なく動作するように見えますが、これが Bad (TM) であるかどうか疑問に思っています - そしてその理由は? (Android および iOS 用のコンパイラでこのコードをまだテストしていません)。
必要に応じてさらに具体的に: 私はcocos2d-xベースのプロジェクトを構築しています。Base
でありCCObject
、DerivedA
のDerivedB
サブクラスですCCLayer
。
階層はDerivedA
and DerivedB
<< CCLayer
<CCNode
ですCCObject
。それらは、相互に排他的な時間に表示される/生きているゲーム シーンです。
DerivedA
呼び出し元オブジェクトをパラメーターとして受け取り、次のようなものを使用して再生を開始し、ゆっくりとフェードインするように別のセレクター( ) をスケジュールする、音楽の再生をセットアップする別の静的関数があります。CCNode
doSomethingA
callerNode->schedule(schedule_selector(DerivedA::doSomethingA), 0.05f);
schedule_selector
Cスタイルのキャストが行うものです。doSomethingA
メンバー変数にアクセスしたり、メンバー関数を呼び出したりしません。静的メンバーにアクセスし、次のような他の静的関数を呼び出します
CocosDenshion::SimpleAudioEngine::sharedEngine()->setBackgroundMusicVolume(sFadeMusicVolume);
doSomethingA
実行時の呼び出しはCCTimer::updateで行われます。
ハックの主な目的は、コードの重複を避け、ライブラリのコールバック シグネチャ (タイマー/スケジューラ システム) に準拠することです。