0

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.

JeJo
  • 30,635
  • 6
  • 49
  • 88
Wambitz
  • 355
  • 1
  • 2
  • 13

1 Answers1

3

The base class is missing the virtual destructor and hence the undefined behaviour. Provide a

virtual ~StrategyInterface() = default;

for defined behaviour. See here

JeJo
  • 30,635
  • 6
  • 49
  • 88