С++: вызвать статическую функцию-член для базового указателя производного объекта другого класса

Изменить: приведенный ниже пример не работает так, как предполагалось. На этот вопрос правильный ответ Стива Джессопа. Создан новый вопрос с исправленным примером. Вопрос может быть удален в зависимости от правил сообщества. Или тело может быть сокращено до «Можно ли вызвать статическую функцию-член (указатель) для указателя базового класса?» с примером ниже, чтобы соответствовать ответу. Раздел более подробная информация (cocos2d-x) под примером может быть удален.

Является ли «безопасным» (и/или переносимым) вызов статической функции-члена (указателя) для указателя базового класса, но объект является другим производным классом.

class Base { /* ... */ }
class DerivedA  : public Base {
    /* ... */ 
    static void doSomethingStaticA(float f);
}
class DerivedB  : public Base { /* ... */ }

typedef void (Base::*SEL_SCHEDULE)(float);
SEL_SCHEDULE pCallback = (&DerivedA::doSomethingStaticA);

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) хорошо, но мне интересно, плохо ли это (TM) и почему? (Мне еще предстоит протестировать этот код с помощью компиляторов для Android и iOS).

Еще немного подробностей, если требуется: я создаю проект на основе cocos2d-x. Base – это CCObject, DerivedA и DerivedB – подклассы CCLayer.

Иерархия DerivedA и DerivedBCCLayerCCNodeCCObject.

DerivedA имеет другую статическую функцию для настройки воспроизведения музыки, которая получает CCNode вызывающий объект в качестве параметра и расписание другого селектор (doSomethingStaticA), чтобы начать воспроизведение, и постепенно затухайте его, используя что-то вроде:

callerNode->schedule(schedule_selector(DerivedA::doSomethingStaticA), 0.05f);

doSomethingStaticA выполняет такие действия, как например

CocosDenshion::SimpleAudioEngine::sharedEngine()->setBackgroundMusicVolume(sFadeMusicVolume);

Вызов doSomethingStaticA во время выполнения происходит в CCTimer::update .


person PAT    schedule 16.04.2013    source источник


Ответы (1)


Вы даже не сможете инициализировать pCallback с помощью &DerivedA::doSomethingStaticA, поскольку указатель на статическую функцию-член на самом деле является указателем на функцию, а не указателем на функцию-член.

Так что что-то Плохо, даже если это просто ваш пример кода ;-) Также b->pCallback может быть b->*pCallback, new возвращает указатель, который нельзя использовать для инициализации db, есть некоторые пропущенные точки с запятой и, возможно, другие проблемы, которые я пропустил. Напишите короткую программу, которая компилируется, опубликуйте ее и задайте свой вопрос об этой программе.

person Steve Jessop    schedule 16.04.2013