我可以使用函数指针调用虚拟析构函数吗?

时间:2018-10-10 09:54:42

标签: c++ explicit-destructor-call

我有Data类,可以容纳指向对象的指针。我希望以后能够手动调用其析构函数,为此我需要将其地址存储在变量中,但似乎禁止采用构造函数/析构函数的地址。有什么办法解决吗?

struct Data {

  union {
    long i;
    float f;
    void* data_ptr;
  } _data;

  std::type_index _typeIndex;
  void (*_destructor_ptr)();

  template<typename T>
  void Init() {
  if constexpr (std::is_integral<T>::value) {
    //
  }
  else if constexpr (std::is_floating_point<T>::value) {
    //
  }
  else {
    _data.data_ptr = new T;
    _typeIndex = std::type_index(typeid(T));
    _destructor_ptr = &T::~T; // << -- can't do this
  }
}

3 个答案:

答案 0 :(得分:9)

存储lambda,并进行适当转换:

void (*_destructor_ptr)(void *v);

// ...

_destructor_ptr = [](void* v) { delete static_cast<T*>(v); };

请注意,您必须为_data.data_ptr传递v。如果打算存储普通函数指针,则lambda可能无法捕获或隐式引用_data.data_ptr

答案 1 :(得分:7)

如果您的编译器不支持lambda,也可以使用以下解决方案:

template<typename T>
struct DestructorHelper {
  static void Destroy(void * v) {
    delete static_cast<T*>(v);
  }
};

并将其用作:

_destructor_ptr = &DestructorHelper<T>::Destroy;

答案 2 :(得分:1)

我还将为智能指针添加一个解决方案:

template <class T>
struct DataPtrDeleter
{
    void operator()(void * p) { delete (T*)p; }
}

std::shared_ptr<void*> data_ptr(new T, DataPtrDeleter<T>());
//or
std::unique_ptr<void*, DataPtrDeleter<T>> data_ptr(new T, DataPtrDeleter<T>());