Is it "safe" (and/or portable) to call a member function (pointer) on the pointer of a base class, but the object pointed to is an instance different derived class. The member function does not access any member variables or functions of the derived class.
/* 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);
This seems to work (in MSVC/Debug mode) okay at runtime, but I'm wondering whether this is Bad (TM) - and why? (I'm yet to test this code with the compilers for Android and iOS).
Some more specifics if required: I'm building a cocos2d-x based project. Base
is CCObject
, DerivedA
and DerivedB
are subclasses of CCLayer
.
The hierarchy is DerivedA
and DerivedB
< CCLayer
< CCNode
< CCObject
. They're game scenes which are visible/alive at mutually exclusive times.
DerivedA
has a different static function to set up playback of music which receives a CCNode
caller object as a parameter and schedules another selector (doSomethingA
) to begin playback and slowly fade it in using something like:
callerNode->schedule(schedule_selector(DerivedA::doSomethingA), 0.05f);
schedule_selector
is what does the C-style cast. doSomethingA
does not access any of its member variables or call member functions. It accesses static members and calls other static functions such as such as
CocosDenshion::SimpleAudioEngine::sharedEngine()->setBackgroundMusicVolume(sFadeMusicVolume);
The call to doSomethingA
at runtime happens in CCTimer::update.
The hack is primarily to avoid duplicating code and conform to the library's callback signature (timer/scheduler system).