Программирование >>  Оптимизация возвращаемого значения 

1 ... 77 78 79 [ 80 ] 81 82 83 ... 96


практическим выходом будет возврат к механизму двойного вызова виртуальных функций, который был рассмотрен ранее. Значит, вам придется примириться с необходимостью перекомпиляции при введении новых классов в иерархию наследования.

Инициализация эмулированных таблиц виртуальных функций (повторно)

Это все, что можно сказать о двойной диспетчеризации, но неприятно заканчивать главу на такой грустной ноте. Поэтому вашему вниманию предлагается набросок альтернативного подхода к инициализации массива collisionMap.

Схема программы до сих пор оставалась полностью статической. Будучи раз зарегистрирована, функция для обработки столкновений объектов двух разных типов остается навсегда. А что, если пользователю захочется добавлять, удалять или изменять функции для обработки столкновений во время игры?

Чтобы сделать это, можно заключить понятие карты, хранящей функции обработки столкновений, в класс, где находятся функции-члены, позволяющие динамически изменять содержимое карты, например:

class CollisionMap { public:

typedef void (*HitFunctionPtr) (GameObjectSc, GameObjectSc); void addEntry (const stringSc typel, const stringSc type2, HitFunctionPtr collisionFunction, bool symmetric = true); См. ниже,

void removeEntry (const stringSc typel,

const stringSc type2) ; HitFunctionPtr loolcup(const stringSc typel,

const StringSc type2) ; Эта функция возвращает ссылку на одну и только одну карту - см. правило 26. static CollisionMapSc theCollisionMap(); private:

Эти функции объявлены как закрытые, чтобы

предотвратить создание нескольких карт - см. правило 26.

CollisionMapО;

CollisionMap (const CollisionMapSc);

Этот класс позволяет добавлять в карту игры новые элементы, удалять их из нее и выполнять поиск функции обработки столкновений, связанную с определенной парой имен типов. Он также использует методы из правила 26, чтобы создавался всего один объект CollisionMap, так как в системе существует всего одна карта. (Можно легко представить себе более сложные игры с несколькими картами.) И наконец, она позволяет упростить добавление к карте симметричных столкновений (то есть если столкновение объекта типа Т1 с объектом типа Т2 имеет тот же эффект, что и столкновение объекта типа Т2 с объектом типа Т1),



CollisionMap::theCollisionMap().addEntry(typel, type2, collisionFunction, symmetric);

После этого пользователи могли бы с помощью глобальных объектов данного типа автоматически регистрировать необходимые им функции:

RegisterCollisionFunction cf1( Spaceship , Asteroid , ScshipAsteroid) ;

автоматически добавляя соответствующую ячейку карты при вызове функции addEntry со значением необязательного параметра symmetric равным true.

Имея такой класс CollisionMap, каждый из пользователей, которому нужно добавить ячейку к карте, делает это напрямую:

void shipAsteroid(GameObjectSc spaceship,

GameObjectSc asteroid) ; CollisionMap::theCollisionMap(.addEntry( Spaceship ,

Asteroid ,

ScshipAsteroid) ; void shipStation(GameObjectSc spaceship, GameObjectSc SpaceStation) ; CollisionMap::theCollisionMap().addEntry( Spaceship ,

SpaceStation ,

ScshipStation) ; void asteroidstation(GameObjectSc asteroid, GameObjectSc SpaceStation) ; CollisionMap::theCollisionMap().addEntry( Asteroid ,

SpaceStation ,

ScasteroidStation) ;

Нужно гарантировать, что ячейки карты будут добавлены до того, как произойдут столкновения, вызывающие связанные с ними функции. Один из способов сделать это - проверять в конструкторах подклассов класса GameObj ect, что соответствующие изображения уже были добавлены к карте при создании каждого объекта. Но такой подход немного снизит производительность программы. В качестве альтернативы можно было бы создать класс Register-CollisionFunction:

class RegisterCollisionFunction { public:

RegisterCollisionFunction(

const StringSc typel,

const StringSc type2,

CollisionMap::HitFunctionPtr collisionFunction, bool symmetric = true)



RegisterCollisionFunction cf2{ Spaceship , SpaceStation , ScshipStation) ;

RegisterCollisionFunction cf3( Asteroid , SpaceStation , basteroidStation);

int main(int argc, char * argv[]) {

Так как эти объекты создаются до вызова функции main, то функции, регистрируемые их конструкторами, также добавляются к карте до вызова функции main. Если позже в игру включается новый производный класс:

class Satellite: public GameObject { ... } ;

И одна или несколько новых функций для обработки столкновений:

void satelliteShip(GameObjectSc satellite, GameObjectSc spaceship); void satelliteAsteroid(GameObject6c satellite, GameObjectSc asteroid);

TO все новые функции вы сможете добавить к карте аналогичным образом, не затрагивая соответствующий код:

RegisterCollisionFunction cf4( Satellite , Spaceship ,

ScsatelliteShip) ; RegisterCollisionFunction cf5{ Satellite , Asteroid ,

ScsatelliteAsteroid) ;

Конечно, это далеко не безупречный способ реализации множественной диспетчеризации (такого попросту нет), но он облегчает ввод данных в основанную на карте реализацию.



1 ... 77 78 79 [ 80 ] 81 82 83 ... 96

© 2006 - 2025 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика