如何在构造函数中包装传递非托管类的类?

时间:2015-07-27 13:44:13

标签: visual-c++ c++-cli wrapper unmanaged managed

我正在尝试理解C ++ / CLI,因此我可以为C ++代码创建Wrapper类。我的问题是我有一个类存储指向该类的父对象的指针,因此我需要将它传递给该类。

下面是一个示例,但完整的类具有更多功能并存储额外数据。

class A
{
private:
    A* parent;

public:
    A(A* Parent)
    {
        parent = Parent;
    }
    ~A()
    {
        delete parent;
    }

    A* GetParent()
    {
        return parent;
    }
}

我目前的想法是拥有一个非公共构造函数,以便您可以使用非托管类构建托管类,而无需在类外部访问它。

public ref class ManagedA
{
    A* unmanaged;

    ManagedA(A* unmanaged)
    {
        this->unmanaged = unmanaged;
    }

public:
    ManagedA(ManagedA^ Parent)
    {
        unmanaged = new A(Parent->unmanaged);
    }

    ~ManagedA()
    {
        delete unmanaged;
        unmanaged = NULL;
    }

    ManagedA^ GetParent()
    {
        return gcnew ManagedA(unmanaged->GetParent());
    }
}

虽然这适用于类中的函数,但是如果我想创建一个对象或者我有一个需要传入非托管类的函数,我仍然会遇到问题。

我有办法解决这个问题吗?

1 个答案:

答案 0 :(得分:2)

ManagedA^ GetParent()
{
    return gcnew ManagedA(unmanaged->GetParent());
}

你用这样的代码射击你的腿,非常危险。问题是,您正在创建多个ManagedA对象,这些对象引用完全相同的A *。一旦一个被破坏,所有其他ManagedA对象现在都有一个悬空指针。这几乎可以保证导致内存损坏。

解决方案非常简单,只需将父引用存储在构造函数中:

public ref class ManagedA {
private:
    A* unmanaged;
    ManagedA^ parent;
public:
    ManagedA(ManagedA^ Parent) : parent(Parent) {
        A* unmanagedParent = Parent == nullptr ? nullptr : Parent->unmanaged;
        unmanaged = new A(unmanagedParent);
    }
    ManagedA^ GetParent() {
        return parent;
    }
    ~ManagedA() {
        this->!ManagedA();
        unmanaged = NULL;
    }
    !ManagedA() {
        delete unmanaged;
    }
};

注意在构造函数中添加了nullptr检查,这是我能看到第一个A *如何被创建的唯一理智的方式。

这很简单,当您需要将A *映射回ManagedA ^时,会发生完全相同的对象身份问题。首先检查是否需要 ,客户​​端代码只能操作ManagedA对象。必要时,您需要创建一个查找表,以便可以可靠地找到相应的ManagedA ^。这需要静态Dictionary<IntPtr, ManagedA^>。在构造函数中将对象添加到字典中,在终结器中删除它们。请注意,您忘记包含终结器,但它不是可选的。我把它添加到了代码段。