自动void *到C ++类转换

时间:2013-07-13 18:53:16

标签: c++ lua

我正在尝试将一些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,但我只需要一个实际执行转换的函数对我来说,我找不到使用模板的任何解决方案。

2 个答案:

答案 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,但我想我会创建一个函数,为这些父母的每个父母和父母自动创建它们。