Является ли статическое приведение хорошим дизайном в моей ситуации?

Я использую менеджер состояния игры (вступление, главное меню, игровой процесс и т. д.) из здесь< /а>. Однако есть одна проблема. Очень минималистичный пример:

class cApp //manages the states and gives them access to window
{
public:
cApp (RenderWindow & ref) : window(ref) {}
void changeState(cState *);     //these function realy doesn't matter
void update();
void draw();

RenderWindow & window; //the same as in the article, this class not only manages state but gives them access to window etc

private:
std::vector <cState *> states;
}

Штат:

class cState
{
public:
cState(cApp * ptr) : app(ptr) {}
virtual void update() = 0;
virtual void draw() = 0;
protected:
cApp * app;
}

Пока все хорошо. Проблема в том, что это часть базовой структуры. Таким образом, cApp является очень простым и дает доступ только к окну. Однако может быть случай, когда пользователь хочет использовать сеть в своей игре. Сетевой движок не является частью единого состояния, поэтому он должен быть на более глобальном (то есть cApp) уровне.

Итак, пользователь делает:

class cNetworkedApp : public cApp
{
public:
cNetworkedApp(RenderWindow & ref1, NetworkEngine & ref2)
: networking(ref2), cApp(ref1)
NetworkEngine & networking; //initialized in cNetworkedApp constructor
}

class CharacterCreationState : public cState
{
 CharacterCreationState(cApp * ptr) : cState(ptr) {}
 //implement pure virtual functions
 void draw()
 {}
 void update()
  {
      //THE PROBLEM
      //the state needs to access the network engine so casting is required
      cNetworkedApp * ptr = static_cast<cNetworkedApp*>(app))
      ptr->networking.sendSomething();
  }
}

Единственное очевидное решение — включить все, что возможно, в cApp, однако, как я уже сказал, это фреймворк. Конечно, некоторые движки, такие как физический движок или звуковой движок, — это вещи, которые вы помещаете в состояние, так что это не проблема, но такие вещи, как сетевая система, должны быть единым объектом, доступным для всех состояний. И не каждое приложение использует его.

Нужно ли мне переделывать этот код или все в порядке?


person user1873947    schedule 14.02.2013    source источник
comment
dynamic_cast даже не будет работать, так как классы не полиморфны.   -  person Luchian Grigore    schedule 14.02.2013
comment
Потратьте время, чтобы написать правильный код в вопросе. В его нынешнем виде определение базы не будет компилироваться. Хотя небольшие ошибки могут быть исправлены при чтении, в данном конкретном случае неясно, являются ли/должны ли быть виртуальными какие-либо функции-члены в базовом типе.   -  person David Rodríguez - dribeas    schedule 14.02.2013
comment
Я изменил код. Теперь все хорошо. ( Я думаю )   -  person user1873947    schedule 14.02.2013
comment
@ user1873947: Нет, это не так.   -  person David Rodríguez - dribeas    schedule 14.02.2013
comment
@ Дэвид Родригес, что случилось? Несмотря на то, что это псевдокод.   -  person user1873947    schedule 14.02.2013
comment
Из моего предыдущего комментария: неясно, являются ли/должны ли какие-либо функции-члены в базовом типе быть виртуальными. Я по-прежнему не вижу ключевого слова virtual. В случае cState вы можете только предполагать, что они есть, поскольку = 0 иначе не скомпилируется, но в случае cApp это неясно. Помните, что проблему нужно решать вы, а не мы. Ваша часть сделки помогает нам понять проблему, наша часть сделки пытается помочь вам прийти к решению. Я лично не буду тратить время, пытаясь угадать ваши намерения.   -  person David Rodríguez - dribeas    schedule 14.02.2013
comment
@ Дэвид Родригес, теперь в коде все предельно ясно. Класс cApp не имеет виртуальных функций.   -  person user1873947    schedule 14.02.2013
comment
@ user1873947: Тогда обратитесь к комментарию Лучиана выше.   -  person David Rodríguez - dribeas    schedule 14.02.2013
comment
@ Дэвид Родригес, вопрос о static_cast.   -  person user1873947    schedule 14.02.2013
comment
Ну, код был неправильным в начале, но теперь в коде все хорошо. Теперь это не псевдокод, а полностью рабочий код.   -  person user1873947    schedule 14.02.2013


Ответы (1)


Ваш cApp может хранить именованный список полиморфного типа Engine, т.е. map<string,Engine*>, затем ваш пользователь может спросить cApp, есть ли у него данный движок.

NetworkEngine будет подклассом чистого абстрактного Engine.

Обновлять

Имея дело с указателем, в котором я уверен, что он имеет заданный специализированный тип, вы должны использовать static_cast, когда вы хотите запросить, может ли указатель быть приведен к типу, вы должны использовать dynamic_cast.

У меня лично есть более безопасный подход для первого случая, я использую утверждение, чтобы гарантировать, что тип может быть приведен, и использовать static_cast в обычном коде:

Engine* fetchedEngine = cApp.fetch("network");
assert( dynamic_cast<NetworkEngine*>(fetchedEngine) != NULL );
NetworkEngine* network = static_cast<NetWorkEngine*>(fetchedEngine);

Только объект типа NetworkEngine должен быть помещен в «сетевое» имя, но, возможно, кто-то по ошибке поместил что-то другое, assert сделает нас более безопасными, не беспокоясь о накладных расходах.

person André Puel    schedule 14.02.2013
comment
интересный подход. Вы правы, отделение менеджера состояний от движка — отличное решение. Я подожду и посмотрю, есть ли у кого-то другое интересное решение. - person user1873947; 14.02.2013
comment
и с этим методом я должен предпочесть dynamic_cast или static_cast? - person user1873947; 14.02.2013
comment
@user1873947 user1873947 Отредактировал мой ответ, посмотри - person André Puel; 14.02.2013
comment
@user1873947 user1873947 Обратите внимание, что для работы dynamic_cast вам понадобится виртуальная таблица. Просто создайте виртуальный деструктор, и все готово. - person André Puel; 14.02.2013