我需要传递一个指向类的指针,所以我无法控制一些代码。这段代码在完成时会自动释放()指针,但我稍后需要该类。我希望我可以创建一个“包装器”类来保持类的释放,而不会实际阻止代码访问它,但虚拟调用不起作用。
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类,但这是我能想到的......
我也无法修改示例,但我可以将其子类化
答案 0 :(得分: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
答案 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(©);
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 *类型(即该类型的值或引用不是指向该类型的指针)。
由于您需要调用的函数不受您控制,因此您需要提供一个完整的包装器,它所期望的类型为您希望控制其生命周期的实例的包装器。