首页 文章

静态虚函数

提问于
浏览
0

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

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

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

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

我相信你能看到问题所在 . 首先,我们需要和实际的实例化来注册一个对象 . 因此,我们可能会为特定类型的对象多次调用此函数,只是让它第一次返回true而每隔一次返回false . 虽然这样做的开销微乎其微,但设计上出现问题却是一件坏事 .

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

1 回答

  • 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; //????
       }
    }
    

相关问题