静态虚函数
Static Virtual Functions
好的,我知道静态虚函数不存在有几个原因。然而,我确实相信,我发现了一种情况,在这种情况下,模仿它们的东西可能会有用。作为 class 小组项目的一部分,我们必须为游戏引擎设计脚本核心。为了保持解耦,我们希望 class 能够使用 LuaState 注册其元表(函数、成员等)。另外,我可能会离开这里,因为这是我第一次尝试实现任何此类东西。
因此,为了保持通用性,我们有一个 IScriptStateManager 接口,该接口包含纯虚函数,用于向脚本语言全局状态注册对象、执行初始化和关闭功能,以及用于 DoFile 和 DoString 的其他几个函数。然后我们有一个LuaStateManagerclass实现了这个接口的功能
现在,为了允许在脚本中创建大多数游戏对象而无需提前知道它们,我们还创建了一个 IScriptObject 接口。如果你想让一个对象由脚本系统来表示,它应该实现这个接口。该接口包含一个方法,该方法包含一个名为 register 的方法,派生 classes 可以实现该方法并将在那里设置元表。所以一切看起来像这样:
bool LuaStateManager::Register(IScriptObject* obj)
{
if (obj has not already been registered with global state)
{
obj->Register();
return true;
}
return false;
}
我相信你能看出问题所在。首先,我们需要实际实例化来注册一个对象。因此,我们可能会为特定类型的对象多次调用此函数,只是第一次 return true 和 false 每隔一次。虽然这样做的开销很小,但它确实表明设计存在问题。
所以问题来了。在这种特殊情况下,我们需要静态方法和虚拟方法的功能。当然,我们可以简单地手动向每个 class 添加静态方法,然后调用它们一次,但这会将对象耦合到脚本系统。任何提示或帮助将是最受欢迎的。谢谢
通过 API class 或命名空间中的一组函数提供对 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; //????
}
}
好的,我知道静态虚函数不存在有几个原因。然而,我确实相信,我发现了一种情况,在这种情况下,模仿它们的东西可能会有用。作为 class 小组项目的一部分,我们必须为游戏引擎设计脚本核心。为了保持解耦,我们希望 class 能够使用 LuaState 注册其元表(函数、成员等)。另外,我可能会离开这里,因为这是我第一次尝试实现任何此类东西。
因此,为了保持通用性,我们有一个 IScriptStateManager 接口,该接口包含纯虚函数,用于向脚本语言全局状态注册对象、执行初始化和关闭功能,以及用于 DoFile 和 DoString 的其他几个函数。然后我们有一个LuaStateManagerclass实现了这个接口的功能
现在,为了允许在脚本中创建大多数游戏对象而无需提前知道它们,我们还创建了一个 IScriptObject 接口。如果你想让一个对象由脚本系统来表示,它应该实现这个接口。该接口包含一个方法,该方法包含一个名为 register 的方法,派生 classes 可以实现该方法并将在那里设置元表。所以一切看起来像这样:
bool LuaStateManager::Register(IScriptObject* obj)
{
if (obj has not already been registered with global state)
{
obj->Register();
return true;
}
return false;
}
我相信你能看出问题所在。首先,我们需要实际实例化来注册一个对象。因此,我们可能会为特定类型的对象多次调用此函数,只是第一次 return true 和 false 每隔一次。虽然这样做的开销很小,但它确实表明设计存在问题。
所以问题来了。在这种特殊情况下,我们需要静态方法和虚拟方法的功能。当然,我们可以简单地手动向每个 class 添加静态方法,然后调用它们一次,但这会将对象耦合到脚本系统。任何提示或帮助将是最受欢迎的。谢谢
通过 API class 或命名空间中的一组函数提供对 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; //????
}
}