防止课程被释放

时间:2012-11-11 01:54:26

标签: c++ c++11

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

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-&gt; virtualfunction()调用PointerWrapper本身的虚函数而不是PointerWrapper-> p中的虚函数。似乎它忽略了 - &gt;运营商?

现在,如果有不同的方法,我不需要使用PointerWrapper-esque类,但这是我能想到的......

我也无法修改示例,但我可以将其子类化

3 个答案:

答案 0 :(得分:4)

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

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

完整代码:

live demo

#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

答案 1 :(得分: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;

答案 2 :(得分:0)

您正在向codeIDontControl提供示例*。重载运算符 - &gt; on PointerWrapper用于PointerWrapper类型而不是Example *类型甚至是PointerWrapper *类型(即该类型的值或引用不是指向该类型的指针)。

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