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()