Reputation: 1346
I'm trying to embed some game classes using a scripting language. Suppose my main structure is:
class BaseGameObject {
public:
virtual ~BaseGameObject() { }
};
class DerivedGameObject : public virtual BaseGameObject {
};
And then, I want to attach information about how I bind this class on the script engine. I want to keep the cohesion with them as minimal as possible, so I've ended with this template pattern:
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>();
}
So I have a factory that build the "wrapped" BaseGameObject and returns the GameObjectLanguageBinder in place. This way, the rest of the system uses the resulting class as a BaseGameObject*, the script language dependency is confined in a set of classes that do not harm the Game ecosystem, and only my Script engine need to know that in fact it is a GameObjectLanguageBinder. This is working very well, aside one point:
To get back the ScriptLanguageBinder object from the BaseGameObject* I need to do this:
ScriptLanguageBinder* binder = dynamic_cast<ScriptLanguageBinder*>(my_game_object);
Which is undesirable as I want to squeeze all performance I can from the code execution (It's a mobile game engine, so yes, performance counts).
So I was wondering if there is some non-obtrusive, transparent way to achieve this without using dynamic cast. I thought in using a Visitor pattern, but this pattern is a blocker when you want to extend the classes you visit, so it's a no go.
ps: the factory is ultra over-simplified on this example.
Upvotes: 0
Views: 107
Reputation: 137940
Just from glancing at the code
The virtual function should be the destructor. An abstract base class is best defined like this:
class BaseGameObject {
public:
virtual ~BaseGameObject() = 0;
};
inline BaseGameObject::~BaseGameObject() {}
The class inheritance should not be virtual
. Virtual inheritance is only used if the base class will be multiply inherited from different branches of the inheritance hierarchy.
The binder should not be derived from BaseGameObject, because it is not a game object. Shouldn't it instead be derived from something like BaseScriptObject
? Am I mistaken or is each expression/variable in the script engine either a reference to a game object or a native type like int
? And the binder implements reference semantics like reference counting?
Upvotes: 1