为什么在使用带有接口指针的多态行为时没有调用析构函数?
Why the destructor has not called when using polymorphic behavior with pointer to interface?
我实现了一个 策略设计模式 ,因此我有一个指向 Context
class 中的接口的指针,因此我可以使用多态性。我想在对象超出范围时调用 Strategy
classes 的 subclass 和 base class 析构函数,但是如果我使用指向接口.
我在 Context
class 中更改了指向 Abstract
class 的指针,一切都按预期工作,当实例退出时调用析构函数范围。另外,我调试了应用程序,智能指针正在释放分配的内存,所以我希望调用其他析构函数。
我想知道为什么在指向接口时不调用析构函数以及保持尽可能高的抽象的正确方法是什么。接口与不尊重调用层次结构的 Abstract
class 有何不同。
我正在使用:
- gcc(x86_64-posix-seh-rev0,由 MinGW-W64 项目构建)8.1.0
- Win10 x64
- 英特尔酷睿 i7 @2.7GHz
- 16 GB 内存
这是我正在测试的代码:
#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;
}
我的预期输出:
Calling base constructor
Hello from SubClass2 constructor
Printing from Base
Hello from SubClass2 destructor
Calling base destructor
注意:当我使用这个 std::unique_ptr<AbstractStrategy> t;
而不是 std::unique_ptr<StrategyInterface> t;
时这有效
我的实际输出:
Calling base constructor
Hello from SubClass2 constructor
Printing from Base
如您所见,当对象超出范围时,不会调用析构函数。
基础 class 缺少虚拟析构函数,因此缺少未定义的行为。
提供
virtual ~StrategyInterface() = default;
对于定义的行为。 See here
我实现了一个 策略设计模式 ,因此我有一个指向 Context
class 中的接口的指针,因此我可以使用多态性。我想在对象超出范围时调用 Strategy
classes 的 subclass 和 base class 析构函数,但是如果我使用指向接口.
我在 Context
class 中更改了指向 Abstract
class 的指针,一切都按预期工作,当实例退出时调用析构函数范围。另外,我调试了应用程序,智能指针正在释放分配的内存,所以我希望调用其他析构函数。
我想知道为什么在指向接口时不调用析构函数以及保持尽可能高的抽象的正确方法是什么。接口与不尊重调用层次结构的 Abstract
class 有何不同。
我正在使用:
- gcc(x86_64-posix-seh-rev0,由 MinGW-W64 项目构建)8.1.0
- Win10 x64
- 英特尔酷睿 i7 @2.7GHz
- 16 GB 内存
这是我正在测试的代码:
#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;
}
我的预期输出:
Calling base constructor
Hello from SubClass2 constructor
Printing from Base
Hello from SubClass2 destructor
Calling base destructor
注意:当我使用这个 std::unique_ptr<AbstractStrategy> t;
而不是 std::unique_ptr<StrategyInterface> t;
我的实际输出:
Calling base constructor
Hello from SubClass2 constructor
Printing from Base
如您所见,当对象超出范围时,不会调用析构函数。
基础 class 缺少虚拟析构函数,因此缺少未定义的行为。 提供
virtual ~StrategyInterface() = default;
对于定义的行为。 See here