4

我需要传递一个指向类的指针,所以我无法控制一些代码。这段代码完成后会自动释放()指针,但我稍后需要这个类。我希望我可以创建一个“包装器”类,以防止该类被释放,而不会真正阻止代码访问它,但虚拟调用不起作用。

template <class T>
class PointerWrapper:public T
{
public:
    T* p;
    PointerWrapper(T *ptr)
    {
        p=ptr;
    }

    ~PointerWrapper(void)
    {
    }
    T* operator->() const
    {
        return p;
    }
    T& operator*() const
    {
        return *p;
    }
};

void codeIDontControl(Example *ex)
{
     ex->virtualfunction();
     delete ex;
}

void myCode()
{
    Example *ex=new Example();

    codeIDontControl(ex);
    do something with ex //doesn't work because ex has been freed

    codeIDontControl(new PointerWrapper<Example>(ex));
    do something with ex //ex hasn't been freed, but the changes made to it via 
    //    Example::virtualfunction() in codeIDontControl() aren't there anymore
}

基本上,ex->virtualfunction() 调用的是 PointerWrapper 本身中的虚函数,而不是 PointerWrapper->p 中的虚函数。似乎它忽略了 -> 运算符?

现在,如果有不同的方法可以做到这一点,我不需要使用 PointerWrapper 类,但这是我能想到的全部......

我也不能修改示例,但我可以将其子类化

4

3 回答 3

4

您应该提供 Forwarder 类 - 它将虚拟调用重定向到存储的指针。释放转发器类不会导致释放指针。这种方法不需要复制(这可能很昂贵/可能没有实现/甚至没有意义):

struct Forwarder : Example
{
    Example *impl;
    Forwarder(Example *i) : impl(i) {}
    void virtualfunction()
    {
        impl->virtualfunction();
    }
};

完整代码:

现场演示

#include <iostream>
#include <ostream>

using namespace std;

struct Example
{
    virtual void virtualfunction()=0;
    virtual ~Example() {}
};

struct Implmenetation : Example
{
    bool alive;
    Implmenetation() : alive(true) {}
    void virtualfunction()
    {
        cout << "Implmenetation::virtualfunction alive=" << alive << endl;
    }
    ~Implmenetation()
    {
        alive=false;
        cout << "Implmenetation::~Implmenetation" << endl;
    }
};

struct Forwarder : Example
{
    Example *impl;
    Forwarder(Example *i) : impl(i) {}
    void virtualfunction()
    {
        impl->virtualfunction();
    }
};

void codeIDontControl(Example *ex)
{
     ex->virtualfunction();
     delete ex;
}

void myCode()
{
    Implmenetation impl;

    codeIDontControl(new Forwarder(&impl));
    //do something with ex //doesn't work because ex has been freed
    impl.virtualfunction();
}
int main()
{
    myCode();
}

输出是:

Implmenetation::virtualfunction alive=1
Implmenetation::virtualfunction alive=1
Implmenetation::~Implmenetation
于 2012-11-11T02:27:23.687 回答
3

这是糟糕的设计,真的。应该只允许分配器释放内存。像这样的函数是危险的,因为它们带有悬空指针。

这只是我的想法,也许你可以尝试这样的事情?这不是一个安全的想法,但如果有人实施它,我很想知道会发生什么。

class Foo
{
  Foo(Foo* copy) : m_copy(copy) {}
  ~Foo() { if(m_copy) { *m_copy = *this; } } // Use copy constructor to create copy on destuction.

  Foo* m_copy;
}


Foo copy(NULL);
Foo* original = new Foo(&copy);
MethodThatDeletes(original);

// Original should be destroyed, and made a copy in the process.
original = NULL;

// Copy should be a copy of the original at it's last know state.
copy;
于 2012-11-11T02:28:13.183 回答
0

您正在向 codeIDontControl 提供 Example*。PointerWrapper 上的重载 operator-> 是 PointerWrapper 类型而不是 Example* 类型甚至是 PointerWrapper* 类型(即该类型的值或引用而不是指向该类型的指针)。

由于您需要调用的函数不是由您控制的,因此您需要提供一个完整的包装器类型,作为您希望控制其生命周期的实例的包装器。

于 2012-11-11T02:11:47.727 回答