自动void*到C++类转换

Automatic void * to C++ class cast

本文关键字:转换 C++ void 自动      更新时间:2023-10-16

我正在尝试将一些C++类绑定到Lua。当使用单一继承时,问题很容易解决,但是当使用多重继承时,确定void*所包含的类的类型会有问题。

Lua只能通过空指针管理用户的数据,所以当你有以下内容时:

#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将自动将指针与B在类C中的位置对齐,如下所述:

int main()
{
        C *c = new C();
        B *b = c;
        printf("c = %p, b = %pn", c, b);
        return 0;
}

输出:

$/a.outc=0x801807040,b=0x80180700

因此,在这里,我们看到B类位于A的大小加上编译器添加的一些内部数据之后。

现在的问题是,如何使用模板将保持类的void指针自动转换为所需类型?我们现在关于void指针的唯一一点是,它还包含一个具有类名的字符串,所以对于a,我们有"a",因此我们可以创建一种要使用的映射。

例如,我希望能够做一些类似的事情

B *b = castFromVoid<B>(myVoidPtr);

因为我知道myVoidPtr的类字符串设置为"C"或"B",所以我确信它可以被强制转换为B,但我只需要有一个函数来真正为我执行强制转换,我找不到任何使用模板的解决方案。

这会是你想要的吗?

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

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

这假设您的所有类都将继承自同一个基类(此处为a),因为RTTI不能在指向void的指针上执行。

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

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