Destructors And Interfaces#
Destructor, Straightforward Usage#
Lets say one of our sensor implementations allocates resources (e.g. by using
new
)⟶ Destructor needed!
Called at exit from function
#include <iostream>
class Sensor
{
public:
virtual double get_value() const = 0;
};
class MySensor : public Sensor
{
public:
MySensor(double value)
: _value(new double{value}) {} // <-- allocation
~MySensor()
{
std::cout << "MySensor::~MySensor()" << std::endl;
delete _value; // <-- deallocation
}
double get_value() const override
{
return *_value;
}
private:
double* _value;
};
#include "sensors.h"
#include <iostream>
int main()
{
MySensor ms{37.3};
return 0; // <-- destructor called
}
$ ./code/destructor-nonvirtual/cxx-inher-oo-destructor-straightforward
MySensor::~MySensor()
Calling Destructor Through Base Class Pointer#
What if
MySensor
object isallocated on the heap?
only a
Sensor*
is used to represent it? (Polymorphic usage)freed using a
Sensor*
?
#include "sensors.h"
#include <iostream>
int main()
{
Sensor* s = new MySensor{37.3};
delete s;
return 0;
}
$ ./code/destructor-nonvirtual/cxx-inher-oo-destructor-base-delete
... remains silent ...
Virtual Destructor (Destructors Are Special)#
Obviously, dynamic dispatch is needed for destructor too
Compiler inserts code to call all destructors along the inheritance chain, up to the very base
⟶ Cannot be
virtual
⟶ Empty
virtual
Solution: Empty Virtual Destructor#
#include <iostream>
class Sensor
{
public:
virtual ~Sensor() = default; // <-- empty!
virtual double get_value() const = 0;
};
class MySensor : public Sensor
{
public:
MySensor(double value)
: _value(new double{value}) {}
~MySensor() override
{
std::cout << "MySensor::~MySensor()" << std::endl;
delete _value;
}
double get_value() const override
{
return *_value;
}
private:
double* _value;
};
#include "sensors.h"
#include <iostream>
int main()
{
Sensor* s = new MySensor{37.3};
delete s; // <-- base pointer used to free derived object
return 0;
}
$ ./code/destructor-virtual-nonempty/cxx-inher-oo-destructor-virtual-nonempty
MySensor::~MySensor()