Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I call a virtual destructor using a function pointer?

I have class Data which can hold a pointer to an object. I want to be able to call its destructor manually later on, for which I need its address stored in a variable but it seems that taking the address of constructor/destructor is forbidden. Is there any way around this ?

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
  }
}
like image 883
const_iterator Avatar asked Oct 10 '18 09:10

const_iterator


People also ask

Can we use this pointer in destructor?

In one word: YES.

Can you call virtual function in destructor?

As a general rule, you should never call virtual functions in constructors or destructors. If you do, those calls will never go to a more derived class than the currently executing constructor or destructor. In other words, during construction and destruction, virtual functions aren't virtual.

Which of the function is used to call destructor?

A destructor is called for a class object when that object passes out of scope or is explicitly deleted. A destructor is a member function with the same name as its class prefixed by a ~ (tilde). For example: class X { public: // Constructor for class X X(); // Destructor for class X ~X(); };

Why should you not call a virtual function from a destructor?

Summary. Virtual functions only “virtually” always behave virtually: Inside constructors and destructors, they don't. Worse, any direct or indirect call to an unimplemented pure virtual function from a constructor or destructor results in undefined behavior.


1 Answers

Store a lambda, suitably converted:

void (*_destructor_ptr)(void *v);

// ...

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

Note that you must pass _data.data_ptr for v. If you intend to store a plain function pointer, the lambda may not capture or implicitly refer to _data.data_ptr.

like image 72
StoryTeller - Unslander Monica Avatar answered Oct 27 '22 10:10

StoryTeller - Unslander Monica