我曾经认为我可以在lua中覆盖一个类方法,这样当我在C ++中调用该函数时,它将执行在lua中重写的内容。我的意思是,像这样:
C ++类
class Person {
public:
Person(); // ctr
virtual void shout(); // Meant to be overriden
};
假设我将该类绑定到lua,以便在lua中,我可以使用该对象:
--Lua code
p = Person:new()
p:shout()
我想要实现的是这样的:
Lua档案
--luafile.lua
p = Person:new() --instantiate
--override shout()
p.shout = function(self) print("OVERRIDEN!") end
C ++代码
int main() {
lua_State* l = lua_open();
luaL_loadlibs(l);
bind_person_class(l);
luaL_dofile("luafile.lua");
Person* p = (Person*) get_userdata_in_global(l, "p"); // get the created person in lua
p->shout(); // expecting "OVERRIDEN" to be printed on screen
lua_close(l);
return 0;
}
在上面的代码中,您可以看到我正在尝试覆盖lua中的Person方法,并期望从c ++调用overriden方法。但是,当我尝试它时,不执行overriden方法。我想要实现的是覆盖方法在C ++中执行。你是如何实现这一目标的?
===================
我已经想到了实现这个目标的方法,但我不确定这是否合适。我的想法是导出的类应该有一个字符串,表示lua中用于保存此类实例的全局变量名。像这样:
class Person {
public:
Person();
string luaVarName; // lua's global variable to hold this class
virtual void shout() {
luaL_dostring(luaVarName + ":shoutScript()"); // now shout will call shoutScript() in lua
}
};
所以,在lua中,对象负责实现shoutScript()并将全局var赋给object:
--LUA
p = Person:new()
p.shoutScript = function(self) print("OVERRIDEN") end
p.luaVarName = "p"
使用上面的代码,我可以实现我想要的(尽管没有测试过)。但是,是否还有其他正确的方法来实现我想要的目标?
答案 0 :(得分:3)
我们在lqt中所做的,Qt与Lua的自动绑定,是对于我们绑定的每个类,它们都有虚拟方法,我们创建一个代理“shell”类,它将自己注册到Lua中状态。
所以对于你的(简化)课程:
class Person {
public:
virtual void shout(); // Meant to be overriden
};
我们生成以下类:
class lqt_shell_Person : public Person {
lua_State *L;
public:
lqt_shell_Person(lua_State *L); // registers itself into the Lua state
virtual void shout();
};
我们使用userdata在Lua中表示这些对象。每个都有自己的环境表,我们指向__newindex
和__index
元方法(__index
函数在环境中查找,然后在类表中查找)。使用此功能,用户可以在对象上存储自定义字段。他还可以实现虚拟功能,如下所示:
p = Person.new()
function p:shout() print("Hello world!") end
在我们的lqt_shell_Person::shout
方法中,我们首先获取参数,然后检查userdata的环境表中是否存在函数shout
。如果有,我们用参数调用它。如果没有,我们称之为原始功能。在抽象方法的情况下,我们抛出Lua错误。
希望你觉得这很有用。
答案 1 :(得分:2)
Lua在“意识形态上”与C ++不同。 Lua是prototype-based OO语言。 C ++是基于类的OO语言。 Lua可以修改对象的接口运行时间,C ++在构造对象后无法修改对象类型。
因此,无论你使用lua对象接口做什么,这些更改都不会反映回C ++程序,而是留在lua中。