2012-03-23 4 views
0

Я пытаюсь внедрить некоторые игровые классы с использованием языка сценариев. Предположим, что моя основная структура:Прозрачная агрегирование классов

class BaseGameObject { 
public: 
    virtual ~BaseGameObject() { } 
}; 

class DerivedGameObject : public virtual BaseGameObject { 

}; 

И потом, я хочу, чтобы прикрепить информацию о том, как я связать этот класс на движке сценариев. Я хочу, чтобы сохранить единство с ними как можно меньше, так что я закончился с этим шаблоном рисунка:

class ScriptLanguageBinder { 
public: 
    virtual void bind(VM* vm) = 0; 
}; 

template < typename GameObject > 
class GameObjectLanguageBinder : public GameObject, public ScriptLanguageBinder { 
    virtual void bind(VM* vm) { 
    vm->bind<GameObject>(static_cast<GameObject*>(this)); 
    } 
}; 

template < typename GameObject > 
BaseGameObject* gameObjectBuilder() { 
    return new GameObjectLanguageBinder<GameObject>(); 
} 

Так что есть завод, которые строят «обернут» BaseGameObject и возвращает GameObjectLanguageBinder на месте. Таким образом, остальная часть системы использует результирующий класс как BaseGameObject *, зависимость языка сценария ограничивается набором классов, которые не вредят экосистеме Game, и только мой движок сценария должен знать, что на самом деле это GameObjectLanguageBinder. Это работает очень хорошо, кроме одной точки:

Чтобы получить обратно объект ScriptLanguageBinder из BaseGameObject * Мне нужно сделать это:

ScriptLanguageBinder* binder = dynamic_cast<ScriptLanguageBinder*>(my_game_object); 

Что нежелательно, так как я хочу, чтобы выжать все производительности, что я могу из исполнение кода (это движок для мобильных игр, так что да, показатели производительности).

Так что мне было интересно, есть ли какой-либо ненавязчивый, прозрачный способ достичь этого без с использованием динамического приведения. Я думал использовать шаблон посетителя, но этот шаблон является блокировщиком, когда вы хотите расширить классы, которые вы посещаете, поэтому это не выход.

пс: завод ultra более-упрощенный на этом примере.

+0

Примечание: Абсолютно нужен виртуальный деструктор, если вы планируете удалить указатель только на базовый класс. Кстати, это может служить одной виртуальной функцией, в которой вы нуждаетесь. : p – Xeo

+0

Да, я это знаю. Классы arent эти, я просто упростил все здесь :) – scooterman

ответ

1

Просто от глядя на код

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

    class BaseGameObject { 
    public: 
        virtual ~BaseGameObject() = 0; 
    }; 
    inline BaseGameObject::~BaseGameObject() {} 
    
  2. Класс наследования не должно быть virtual. Виртуальное наследование используется только в том случае, если базовый класс будет многократно унаследован от разных ветвей иерархии наследования.

  3. Связующее не должно быть получено из BaseGameObject, потому что это не игровой объект. Разве это не должно происходить из чего-то вроде BaseScriptObject? Я ошибаюсь или каждое выражение/переменная в движке скрипта либо ссылается на игровой объект, либо на собственный тип, например int? И связующее реализует ссылочную семантику, например, подсчет ссылок?

+0

Да, 1 и 2 и 3 были ошибками, в то время как я упрощал реальный код при создании вопроса. Я обновил его сейчас :). Связующее должно сделать видимыми функции и переменные из собственного объекта в VM VM сценариев. Но это не те точки. Я хочу знать, есть ли способ избежать динамического кастинга. – scooterman

Смежные вопросы