I implemented a strategy design pattern, therefore I have a pointer to an interface in the Context
class so I can use polymorphism. I want to call the subclass and base class destructor of Strategy
classes when the object goes out of scope, nevertheless this not happen if I use a pointer to the interface.
I changed the pointer to the Abstract
class in the Context
class and everything works as expected, the destructors are being called when the instance goes out of scope. Also, I debugged the application and the smart pointers are releasing the allocated memory so I would expect the other destructors to be called.
I would like to know why the destructors are not called when the interface is pointed to and what is the right approach to keep the abstraction as high as possible. How the interface is different from the Abstract
class that calling hierarchy is not respected.
I'm using:
- gcc (x86_64-posix-seh-rev0, Built by MinGW-W64 project) 8.1.0
- Win10 x64
- Intel Core i7 @2.7GHz
- 16 GB RAM
Here is the code I'm testing with:
#include <iostream>
#include <string>
#include <memory>
class StrategyInterface
{
public:
virtual void print() = 0;
};
class AbstractStrategy : public StrategyInterface
{
private:
int a;
public:
AbstractStrategy();
virtual ~AbstractStrategy();
virtual void print() { std::cout << "Printing from Base\n"; }
};
AbstractStrategy::AbstractStrategy()
{
std::cout << "Calling base constructor\n" ;
}
AbstractStrategy::~AbstractStrategy()
{
std::cout << "Calling base destructor" ;
}
class ConreteStrategy1 : public AbstractStrategy
{
public:
ConreteStrategy1() { std::cout << "Hello from SubClass1 constructor \n"; }
~ConreteStrategy1() { std::cout << "Hello from SubClass1 destructor \n"; }
};
class ConreteStrategy2 : public AbstractStrategy
{
public:
ConreteStrategy2() { std::cout << "Hello from SubClass2 constructor \n"; }
~ConreteStrategy2() { std::cout << "Hello from SubClass2 destructor \n"; }
};
class Context
{
public:
Context(int a)
{
if (a)
{
t = std::make_unique<ConreteStrategy1>();
t->print();
}
else
{
t = std::make_unique<ConreteStrategy2>();
t->print();
}
}
~Context() = default;
private:
std::unique_ptr<StrategyInterface> t;
};
void test()
{
Context context(0);
}
int main(int argc, char const *argv[])
{
test();
return 0;
}
My expected output:
Calling base constructor
Hello from SubClass2 constructor
Printing from Base
Hello from SubClass2 destructor
Calling base destructor
Note: this works when I use this std::unique_ptr<AbstractStrategy> t;
instead of std::unique_ptr<StrategyInterface> t;
My actual output:
Calling base constructor
Hello from SubClass2 constructor
Printing from Base
As you can see the destructor is not being called when the object goes out of scope.