静态虚函数

时间:2015-01-17 07:02:34

标签: c++ lua

好的,我知道静态虚拟功能由于多种原因而不存在。但我相信,我发现了一种模仿它们的东西可能有用的情况。作为类的组项目的一部分,我们必须为游戏引擎设计脚本核心。为了使事物解耦,我们希望一个类能够使用LuaState注册其元表(函数,成员等)。此外,我可能会离开这里,因为这是我第一次尝试实施此类任何东西。

因此,为了保持通用性,我们有一个IScriptStateManager接口,它包含纯虚函数,用脚本语言全局状态注册对象,执行init和shutdown功能,还有一些DoFile和DoString的其他函数。然后我们有一个LuaStateManager类来实现这个接口的功能。

现在,为了允许在脚本中创建大多数游戏对象而不提前知道它们,我们还创建了一个IScriptObject接口。如果您希望脚本系统表示对象,则应实现此接口。此接口包含一个方法,该方法包含一个名为register的方法,派生类可以实现该方法并在其中设置元表。所以一切都是这样的:

bool LuaStateManager::Register(IScriptObject* obj)
{
    if (obj has not already been registered with global state)
    {
          obj->Register();   
          return true;
    }
    return false;
}

我确定你能看到问题所在。首先,我们需要和实际的实例化来注册一个对象。因此,我们可能会为特定类型的对象多次调用此函数,只是让它第一次返回true而每隔一次返回false。虽然这方面的开销微乎其微,但设计出现问题却是一个不可错过的赠品。

所以问题出现了。在这种特殊情况下,我们需要静态方法和虚方法的功能。当然,我们可以简单地手动将静态方法添加到每个类,然后调用一次,但这会将对象耦合到脚本系统。任何提示或帮助将是最受欢迎的。感谢

1 个答案:

答案 0 :(得分:1)

通过API类或命名空间中的一组函数提供对IScriptStateManager功能的访问。

ScriptStateManagerAPI.h:

namespace ScriptStateManagerAPI
{
   // Function to register the active ScriptStateManager.
   void setActiveScriptStateManager(IScriptStateManager* scriptStateManager);

   // Function to register a ScriptObject.
   bool registerScriptObject(IScriptObject* obj);
}

IScriptStateManager.h:

class IScriptStateManager
{
   virtual bool registerScriptObject(IScriptObject* obj) = 0;
};

ScriptStateManagerAPI.cpp:

#include <IScriptStateManager.h>

namespace ScriptStateManagerAPI
{
   static IScriptStateManager* activeScriptStateManager = nullptr;

   void setActiveScripStatetManager(IScriptStateManager* scriptStateManager)
   {
      activeScriptStateManager = scriptStateManager;
   }

   bool registerScriptObject(IScriptObject* obj)
   {
      if ( activeScriptStateManager )
      {
         return activeScriptStateManager->registerScriptObject(obj);
      }
      else
      {
         // Deal with lack of an active IScriptStateManager.
         return false;
      }
   }
}

LuaScriptManager.h:

#include <IScriptStateManager.h>

class LuaScriptManager : public IScriptStateManager
{
   virtual bool registerScriptObject(IScriptObject* obj);
};

LuaScriptManager.cpp:

namespace
{
   // Helper class in anonymous namespace to register a LuaScriptManager as
   // the active IScriptStateManager at start up time.
   struct Initializer
   {
      Initializer();
   };
};

// Construct an Initializer at start up time.
static Initializer initializer;

Initializer::Initializer()
{
   // Register a LuaScriptManager as the acive ScriptStateManager.
   ScriptStateAPI::setActiveScriptStateManager(new LuaScriptManager());
}

bool LuaScriptManager::registerScriptObject(IScriptObject* obj)
{
   if (obj has not already been registered with global state)
   {
      obj->Register();   
      return true;
   }
   return false;
}

您可以在应用中使用其他ScriptStateManager。然后,您必须选择是否一次只能有一个ScriptStateManager。如果您的应用一次需要多个ScriptStateManager,则可以更改static数据以及ScriptStateManagerAPI

中的界面

ScriptStateManagerAPI.h:

namespace ScriptStateManagerAPI
{
   // Function to register an active ScriptStateManager.
   void registerActiveScriptStateManager(IScriptStateManager* scriptStateManager);

   // Function to register a ScriptObject.
   bool registerScriptObject(IScriptObject* obj);
}

ScriptStateManagerAPI.cpp:

#include <IScriptStateManager.h>

namespace ScriptStateManagerAPI
{
   static std::set<IScriptStateManager*> activeScriptStateManagers;

   void registerActiveScripStatetManager(IScriptStateManager* scriptStateManager)
   {
      activeScriptStateManagers.insert(scriptStateManager);
   }

   bool registerScriptObject(IScriptObject* obj)
   {
      // Figure out how to manage the return the values of each
      // activeScriptManager.
      for ( auto activeScriptManager, activeScriptStateManagers)
      {
         activeScriptManager->registerScriptObject(obj);
      }
      return true; //????
   }
}