【发布时间】:2015-05-10 01:12:57
【问题描述】:
我想创建一个主要包含静态成员/方法的基类,例如:
class LuaObject {
public:
static const luaL_Reg Methods[];
static int Create(lua_State *L);
static LuaObject* get(lua_State *L, int pos) {
return *(LuaObject**)luaL_checkudata(L, pos, LuaObject::Metatable);
}
};
然后从中派生出特定类型的对象:
class Pulse: public LuaObject {
public:
int n;
//...
};
const luaL_Reg Pulse::Methods[] = {
//...
};
static int Pulse::Create(lua_State *L) {
Pulse **ud = (Pulse**)lua_newuserdata(L, sizeof(Pulse*));
*ud = new Pulse();
//...
}
但是,如果没有大量的复制和粘贴,我不知道该怎么做(违背了LuaObject 的目的)。出现两个问题:
我收到如下错误:
error: ISO C++ does not permit ‘LuaObject::Methods’ to be defined as ‘Pulse::Methods’ [-fpermissive]和error: no ‘int Pulse::Create(lua_State*)’ member function declared in class ‘Pulse’。也就是说,Pulse似乎没有从LuaObject继承静态成员/方法。-
get(L, n)方法旨在返回指向类实例的指针,例如我希望能够写:脉冲 *p = 脉冲::get(L,1); printf("p->n = %d\n", p->n);但是,似乎因为
get只为LuaObject定义,所以我会得到LuaObject*,而不是Pulse*。
如何解决这些问题,而不必将Methods、Create、get 等复制到Pulse(以及从LuaObject 派生的所有其他类)?
我认为将其转换为模板可能会有所帮助:
template <class T>
class LuaObject {
public:
static const luaL_Reg Methods[];
static int Create(lua_State *L);
static T* get(lua_State *L, int pos) {
return *(T**)luaL_checkudata(L, pos, T::Metatable);
}
};
class Pulse: public LuaObject<Pulse> {
public:
//...
};
但即使这样也给出了同样的错误,所以我很难过。
编辑:根据要求,一个最小的示例程序,包括编译错误:(使用g++ test.cpp -Llua -Lpulse -o test构建)
#include <stdio.h>
#include <stdlib.h>
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
#include <pulse/pulseaudio.h>
class LuaObject {
public:
static const char *Metatable;
static const luaL_Reg Methods[];
static void InitModule(lua_State *L);
static int Create(lua_State *L);
//Retrieve object instance from Lua stack at specified position
static LuaObject* get(lua_State *L, int pos) {
return *(LuaObject**)luaL_checkudata(L, pos, LuaObject::Metatable);
}
};
class Pulse: public LuaObject {
//Here I want to avoid having to declare/define Metatable, get() etc again.
public:
static int getEvent(lua_State *L);
pa_context *ctx;
};
const char *Pulse::Metatable = "pulse"; //error: ISO C++ does not permit ‘LuaObject::Metatable’ to be defined as ‘Pulse::Metatable’ [-fpermissive]
const luaL_Reg Pulse::Methods[] = { //error: ISO C++ does not permit ‘LuaObject::Methods’ to be defined as ‘Pulse::Methods’ [-fpermissive]
{"getEvent", Pulse::getEvent},
{NULL, NULL}
};
//Set up the "pulse" module in a Lua state
static void Pulse::InitModule(lua_State *L) { //error: no ‘void Pulse::InitModule(lua_State*)’ member function declared in class ‘Pulse’
if(luaL_newmetatable(L, Pulse::Metatable)) {
luaL_setfuncs(L, Pulse::Methods, 0);
}
lua_pop(L, 1); //remove metatable from Lua stack, leave in Lua registry
static luaL_Reg lib[] = {
{"new", Pulse::Create},
{NULL, NULL}
};
luaL_newlibtable(L, lib);
lua_setglobal(L, "pulse");
}
//Called from Lua (as pulse.new()) to create a Pulse object
static int Pulse::Create(lua_State *L) { //error: no ‘int Pulse::Create(lua_State*)’ member function declared in class ‘Pulse’
Pulse **ud = (Pulse**)lua_newuserdata(L, sizeof(Pulse*));
*ud = new Pulse();
return 1;
}
//Called from Lua (as myPulse:getEvent()) to read events
int Pulse::getEvent(lua_State *L) {
//We only have L as parameter; the Pulse object is on the Lua stack,
//so we need to read it using luaL_checkudata() (which is handled
//by get())
Pulse *self = Pulse::get(L, 1); //error: invalid conversion from ‘LuaObject*’ to ‘Pulse*’ [-fpermissive]
//pretend get_pulse_event() is defined in pulseaudio.h (the actual mechanism
//is much more complex and wouldn't help the example)
int event = get_pulse_event(self->ctx);
lua_pushinteger(L, event);
return 1;
}
int main(int argc, char **argv) {
lua_State *L = luaL_newstate();
luaL_openlibs(L);
Pulse::InitModule(L);
return luaL_dofile(L, "main.lua");
}
【问题讨论】:
-
嗯...为什么首先需要一个包含所有静态方法的对象?也许那些静态方法应该只是独立的方法。有点像在标准库中使用容器和算法完成的。
get方法是静态的,这看起来也很奇怪。它看起来更像是一个设计问题。话虽如此,这个问题,为什么你的尝试不起作用,无论如何都很有趣。 -
这个想法是让继承的类,如
Pulse,都具有相同的方法,而不必复制它们。我不知道该怎么做。需要get,因为Lua 只给出void*。 (我想我可以投射,但这有点难看) -
不,不,不。我不是在问继承。我在问为什么一切都是静态的。这令人困惑。
get之类的东西应该与一个实例相关联,至少这是我的直觉。您还应该发布一个最小的违规示例。好像您在派生类中重新声明了一个静态成员并搞砸了更多事情。 -
get不能绑定到实例,因为这是我们首先检索实例的方式。当 Lua 调用我们的方法时,它只传递一个lua_State*,我们必须从中检索实际参数(例如Pulse*)。
标签: c++ class inheritance static-methods static-members