我正在尝试将一些C ++类绑定到Lua。使用单继承时,问题非常容易,但是在使用多重继承时,确定void *所持有的类的类型存在问题。
Lua只能通过void指针管理用户的数据,所以当你有以下内容时:
#include <string>
class A {
public:
A() { }
~A() { }
};
class B {
private:
std::string m_name;
int m_count;
public:
B() { }
~B() { }
};
class C
: public A
, public B
{
private:
std::string m_title;
public:
C() { }
~C() { }
};
声明指向C并将其强制转换为B会自动将指针指向C类中B的位置,如下所示:
int main()
{
C *c = new C();
B *b = c;
printf("c = %p, b = %p\n", c, b);
return 0;
}
输出:
$ ./a.out c = 0x801807040,b = 0x801807050
所以在这里,我们看到B类位于A的大小之后,加上编译器添加的一些内部数据。
现在问题是,如何使用模板自动将保存类的void *指针转换为所需类型?我们现在唯一关于void指针的是它还包含一个带有类名的字符串,所以对于A,我们有“A”,因此我们可以创建一种要使用的地图。
例如,我希望能够做类似
的事情B *b = castFromVoid<B>(myVoidPtr);
因为我知道myVoidPtr的类字符串设置为“C”或“B”,我确信它可以转换为B,但我只需要一个实际执行转换的函数对我来说,我找不到使用模板的任何解决方案。
答案 0 :(得分:0)
这可能是你想要的吗?
template<typename T>
T *castFromVoid(void *ptr) {
return dynamic_cast<T *>(static_cast<A *>(ptr));
}
但是,您需要在编译器中启用RTTI,并且在类中至少有一个虚拟方法(析构函数是一个很好的候选者,不是吗?)。
这假设您的所有类都将继承自同一个基类(此处为A),因为无法对指向void的指针执行RTTI。
答案 1 :(得分:0)
我终于使用from-to基础做了一些地图。我们知道字符串的类型我做这样的事情:
typedef std::function<void * (void *)> Converter;
map<string, map<string, Converter>> converters;
template <class From, class To>
void createConverter(string fromName, string toName)
{
converters[toName][fromName] = [&] (void *ptr) -> void * {
From *from = static_cast<From *>(ptr);
return static_cast<To *>(from);
};
}
template <class To>
To * getPointer(string fromName, string toName, void *ptr)
{
return static_cast<To *>(converters[toName][fromName](ptr));
}
int main()
{
createConverter<C, A>("C", "A");
createConverter<C, B>("C", "B");
C *c = new C();
B *b = getPointer<B>("C", "B", c);
// Use b here..
return 0;
}
唯一的缺点是你需要为每种可能性调用createConverter,但我想我会创建一个函数,为这些父母的每个父母和父母自动创建它们。