静态虚函数

好的,我知道静态虚函数由于几个原因而不存在。然而,我认为我找到了一种类似它们的情况可能会很有用。作为课程小组项目的一部分,我们必须为游戏引擎设计脚本核心。为了保持解耦,我们希望一个类能够注册其元表(函数、成员等)到LuaState中。此外,由于这是我第一次尝试实现此类事物,我可能完全错误。

因此,为了保持通用,我们有一个IScriptStateManager界面,其中包含纯虚函数以将对象注册到脚本语言的全局状态中,执行初始化和关闭功能,并具有一些其他功能DoFileDoString。然后我们有一个实现此界面功能的LuaStateManager类。

现在,为了允许大多数游戏对象在脚本中创建而不预先知道它们,我们还创建了一个IScriptObject接口。如果要使对象由脚本系统表示,应实现此接口。此接口包括一个方法,其中包含register称为的方法,派生类可以实现并将设置其元表。因此,一切都像这样:

bool LuaStateManager::Register(IScriptObject* obj)
{
    if (未在全局状态中注册 obj)
    {
          obj->Register();
          return true;
    }
    返回假;
}

我相信您可以看到问题。首先,首先我们需要一个实际的实例来注册一个对象。由于这个原因,我们可能会为一个特定类型的对象多次调用此函数,只有第一次返回真,其他每次都返回假。虽然这样做的开销很小,但它是设计有误的明显迹象。

因此,问题出现了。在这种特殊情况下,我们需要静态方法和虚方法的功能。可以授予我们的草案。虽然我们可以简单地手动向每个类添加静态方法,然后调用那些方法一次,但这会将对象与脚本系统耦合。任何提示或帮助都将不胜感激。谢谢

点赞
用户434551
用户434551

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

ScriptStateManagerAPI.h:

namespace ScriptStateManagerAPI
{
   // 将活动的 ScriptStateManager 注册到函数中。
   void setActiveScriptStateManager(IScriptStateManager* scriptStateManager);

   // 注册 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
      {
         // 处理没有活动 IScriptStateManager 的情况。
         return false;
      }
   }
}

LuaScriptManager.h:

#include <IScriptStateManager.h>

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

LuaScriptManager.cpp:

namespace
{
   // 在匿名命名空间中的帮助类,用于在启动时将 LuaScriptManager 注册为活动的 IScriptStateManager。
   struct Initializer
   {
      Initializer();
   };
};

// 在启动时构造一个初始化程序。
static Initializer initializer;

Initializer::Initializer()
{
   // 注册 LuaScriptManager 为活动的 ScriptStateManager。
   ScriptStateAPI::setActiveScriptStateManager(new LuaScriptManager());
}

bool LuaScriptManager::registerScriptObject(IScriptObject* obj)
{
   if (obj 还未在全局状态中注册)
   {
      obj->Register();
      return true;
   }
   return false;
}

您可以在应用程序中使用另一个 ScriptStateManager。然后,您必须选择每次是否只能有一个 ScriptStateManager。如果您的应用程序需要同时使用多个 ScriptStateManager,则可以更改 ScriptStateManagerAPI 中的 static 数据以及接口

ScriptStateManagerAPI.h:

namespace ScriptStateManagerAPI
{
   // 注册活动的 ScriptStateManager 的函数。
   void registerActiveScriptStateManager(IScriptStateManager* scriptStateManager);

   // 注册 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)
   {
      // 找出如何管理每个 activeScriptManager 的返回值。
      for ( auto activeScriptManager, activeScriptStateManagers)
      {
         activeScriptManager->registerScriptObject(obj);
      }
      return true; //????
   }
}
2015-01-18 06:12:38