K-R*_*RAN 3 c++ smart-pointers object-destruction object-slicing
假设我们有一个base班级和一个班级derived.所以:
class base {
protected:
~base(){
//...
}
// ...
};
class derived : public base {
// ...
};
Run Code Online (Sandbox Code Playgroud)
现在说我们使用上面的类和智能指针类有这个代码:
SmartPointer<base> bptr(new derived());
delete bptr;
Run Code Online (Sandbox Code Playgroud)
我知道它会derived通过调用析构函数来阻止对象的切片derived,但它如何知道呢?存储在智能指针中的引用不会是类型的引用base*吗?它是否遍历某种层次结构树,将该指针强制转换为derived*然后调用delete?还是有其他一些我不知道的事情?
该实现被认为是线程安全的,非侵入式的和引用计数.
是的,你看到的类类似于我正在测试的类.显然有一种方法可以使用THESE GIVEN课程.关于如何在上面的问题中提到的主要想法,但我不确定这样的实现如何工作.
首先,它代表不起作用.析构函数base必须至少protected(或派生类是基础的朋友).一个private析构函数意味着编译器不会让你写的析构函数派生类.现在,假设你有一个protected析构函数...(Rembember,如果你设计一个要扩展的类,提供一个公共虚拟析构函数或一个受保护的非虚函数!)
一切都取决于具体的实施SmartPointer,特别是std::shared_ptr(或者提升对应物boost::shared_ptr)能够干净地管理这种情况.该解决方案执行某种类型的部分类型擦除以用于销毁目的.基本上,智能指针有一个模板化的构造函数,它接受任何可以分配给base指针的指针,但由于它是模板化的,因此它知道具体的类型.此时它存储一个合成deleter函数,该函数将调用适当的析构函数.
为简单起见,使用std::function:
template <typename T>
void delete_deleter( void * p ) {
delete static_cast<T*>(p);
}
template <typename T>
class shared_pointer {
T * ptr;
std::function<void(void*)> deleter;
public:
template <typename U>
shared_pointer( U* p, std::function<void()> d = delete_deleter<U> )
: ptr(p), deleter(d)
{}
~shared_pointer() {
deleter( ptr ); // call the stored destructor
}
};
Run Code Online (Sandbox Code Playgroud)
代码仅用于展览,它必须进行调整以进行生产(在哪里存储function,引用计数...),但它足以给你一个想法:在唯一的函数中,对象的确切类型是已知(在创建智能指针时),您创建一个包装器,它将调用所需的析构函数的确切版本(提供一些类型的擦除),然后将其保留,当您需要delete对象调用它而不是该delete运营商.
这也可用于管理需要调用特殊方法的其他资源,而不是delete:
// exhibition only!
shared_pointer<Foo> p( Factory.create(), &Factory::release );
Run Code Online (Sandbox Code Playgroud)
在准备好这个生产之前,应该有相当多的工作.
std::function可以从问题中消除用于简化擦除的依赖性.在简单的情况下(在智能指针中仅支持分配new和释放的内存delete),然后只提供deleter具有单个虚拟的基类operator()(void*),然后使用当前实现delete_deleter从现有的deleter重写中重构现有的模板化派生类operator()(void*).如果你需要寻找一般情况(持有任何类型的资源),那就不值得努力,只需使用std::function或boost::function.