1

我正在尝试将一些 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,但我只需要一个真正为我做转换的函数我没有找到任何使用模板的解决方案。

4

2 回答 2

0

我终于用从到到的地图做了一些事情。正如我们通过字符串知道类型我做这样的事情:

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

于 2013-07-13T19:56:59.543 回答
0

这可能是你想要的吗?

template<typename T>
T *castFromVoid(void *ptr) {
    return dynamic_cast<T *>(static_cast<A *>(ptr));
}

但是,您需要在编译器中启用 RTTI,并且在您的类中至少有一个虚拟方法(析构函数是一个很好的候选者,不是吗?)。

这假设您的所有类都将继承自同一个基类(此处为 A),因为无法对指向 void 的指针执行 RTTI。

于 2013-07-13T19:31:25.760 回答