继承和存储静态类信息

时间:2010-06-23 06:33:30

标签: c++ inheritance templates static-members

我正在尝试用Lua设置一些东西,但Lua的细节对我的问题并不重要。

我希望能够做的是调用一个函数,比如OpenLib<T>(L),并让它获取特定类(以及它的表)的表名,并将其注册到Lua。它基本归结为:

template <class T>
static void OpenLib(lua_State* L)
{
    // this func does some other stuff too that I'm omitting, important bit below
    if (T::myTable && T::myTableName)
    {
        luaL_openlib(L, T::myTableName, T::myTable, 0);
    }
}

我尝试了几种不同的方法,但我无法让它正常工作。我尝试创建一个包含myTable和myTableName的基类,如下所示:

class LuaInfo
{
public:
    static const char* myTableName;
    static luaL_reg* myTable;
}

然后我可以继承LuaInfo,然后填写我需要的信息。这不起作用,因为从LuaInfo继承的所有类都会获得相同的信息,所以我环顾四周并想到了这样做:

template <class t>
class LuaInfo
// ...

这使得初始化它的语法有点傻,因为我现在必须做类Widget:public LuaInfo,但它更接近于工作。

template <class T>
void OpenLib(lua_State* L)
{
    if (T::myTable && T::myTableName)
    {
        luaL_openlib(L, LuaInfo<T>::myTableName, LuaInfo<T>::myTable, 0);
    }
}

我尝试了一些这方面的变种试图让它正确,但我不断收到像

这样的错误
undefined reference to `ag::LuaInfo<ag::ui::Widget>::myTable'

我想做的是什么,如果是的话,最好的方法是做什么?

2 个答案:

答案 0 :(得分:1)

使用

template<typename T>
class LuaInfo
{
  static const char* myTableName;
  static lua_reg* myTable;
};

应该可以正常工作。

您的问题是您需要定义静态变量。

包含一堆这样的行的单个源文件将解决它

luaL_reg* LuaInfo<ag::ui::Widget>::myTable = 0;
const char * LuaInfo<ag::ui::Widget>::myTableName = 0;

luaL_reg* LuaInfo<ag::ui::OtherClass>::myTable = 0;
const char * LuaInfo<ag::ui::OtherClass>::myTableName = 0;

等等。

你可能想要定义一个宏来使这个更好。

#define LUAINFOIMPL(X) luaL_reg* LuaInfo<X>::myTable=0; const char * LuaInfo<X>::myTableName=0
LUAINFOIMPL( ag::ui::Widget );
LUAINFOIMPL( ag::ui::OtherClass );

然而,按比例缩放它有点难看。我在想Traits样式模板可能会解决这个问题..但我不确定它们是否能更好地扩展。

答案 1 :(得分:0)

你的第一次尝试对我来说很好。我想你只是忘了初始化静态成员并得到一些链接错误。这就是我所做的:

template <class T>
static void OpenLib(lua_State* L)
{
    // this func does some other stuff too that I'm omitting, important bit below
    if (T::myTable && T::myTableName)
    {
        luaL_openlib(L, T::myTableName, T::myTable, 0);
    }
}

class LuaInfo
{
    public:
        static const char* myTableName;
        static luaL_reg* myTable;
};

//init static members
const char*  LuaInfo::myTableName = 0;
luaL_reg* LuaInfo::myTable = 0;

int main()
{
    OpenLib<LuaInfo>(0);
}

现在,如果您想向OpenLib提供其他信息,您必须创建一个新类LuaInfo,并将该新类作为模板参数。

但为什么要将此信息作为模板参数? IMO,这更简单:

struct LuaInfo
{
    const char* myTableName;
    luaL_reg* myTable;
};

static void OpenLib(lua_State* L, LuaInfo info)
{
    // this func does some other stuff too that I'm omitting, important bit below
    if (info.myTable && info.myTableName)
    {
        luaL_openlib(L, info.myTableName, info.myTable, 0);
    }
}

int main()
{
    LuaInfo info = {/*some values here*/};
    OpenLib(0, info);
}