假设我们有一个base类和一个derived。所以:

class base {
     protected:
          ~base(){
                //...
          }
     // ...
};

class derived : public base {
     // ...
};

现在,我们使用上面的类和智能指针类来编写此代码:
SmartPointer<base> bptr(new derived());
delete bptr;

我知道它会通过调用derived的析构函数来阻止derived对象的切片,但是它怎么知道这样做呢?存储在智能指针中的引用不是base*类型的引用吗?它是否遍历某种层次结构树,将该指针转换为derived*,然后调用delete?还是还有其他我不知道的事情?

据称该实现是线程安全的,非侵入式的和引用计数的。

,您看到的类类似于我正在测试的类。显然,使用THESE GIVEN类可以做到这一点。在上面的问题中提到了有关如何操作的主要思想,但是我不确定这样的实现将如何工作。

最佳答案

第一件事是,按原样,该代码将无法正常工作。 base的析构函数至少必须是protected(或派生类是基础的 friend )。 private析构函数意味着编译器不允许您为派生类编写析构函数。现在,假设您有一个protected析构函数...(记住,如果您设计要扩展的类,请提供一个公共(public)虚拟析构函数或一个 protected 非虚构函数!)

一切都取决于SmartPointer的实现,特别是std::shared_ptr(或增强版对应的boost::shared_ptr)能够干净地管理这种情况。该解决方案执行某种类型的部分类型擦除,以实现销毁目的。基本上,智能指针具有模板化的构造函数,该构造函数接受可以分配给base指针的任何指针,但是由于它是模板化的,因此它知 Prop 体的类型。那时,它存储了一个合成的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
    }
};

该代码仅用于展示,必须对其进行调整以进行生产(在哪里存储function,引用计数...),但这足以给您一个想法:在唯一的函数中,对象的确切类型是已知的(在创建智能指针时),您将创建一个包装器,该包装器将调用所需的析构函数的确切版本(提供某种类型的擦除),然后将其保留下来,并在需要对对象进行delete调用时将其调用而不是delete运算符。

这也可以用于管理其他需要调用特殊方法而不是delete的资源:
// exhibition only!
shared_pointer<Foo> p( Factory.create(), &Factory::release );

同样,在准备好生产之前,应该做很多工作。

可以从问题中消除对用于简化擦除操作的std::function的依赖性。在简单的情况下(智能指针仅支持分配了new并释放了delete的内存),然后只需提供一个带有单个虚拟deleteroperator()(void*)基类,然后将现有delete_deleter重构为覆盖deleteroperator()(void*)的模板化派生类与当前的实现。如果您需要处理一般情况(保留任何类型的资源),这是不值得的,只需使用std::functionboost::function即可。

09-07 06:26