Seb*_*der 7 c++ polymorphism inheritance destructor
最近在求职面试中,当基类的析构函数未被声明为虚拟时,我被问及派生类中的内存泄漏问题.
我写了一个小测试来确认我的答案,但我发现了一些有趣的东西.显然,如果你Derived
通过创建一个对象new
但将其指针存储为a Base*
,如果指针被删除,则不会调用派生对象的析构函数(这对我对问题的回答非常多).
我认为派生类的析构函数是否是虚拟的在这种情况下是相关的,但在我的系统上,以下代码显示:
#include <iostream>
#include <string>
// just a helper class, printing its name out when it is destructed
class PrintOnDestruct
{
public:
PrintOnDestruct( const std::string& name )
: name_( name )
{}
~PrintOnDestruct()
{
std::cout << "Destructing: " << name_ << std::endl;
}
protected:
std::string name_;
};
// the Base class
class Base
{
public:
Base()
{
print_on_destruct_ = new PrintOnDestruct( "Base" );
}
// the destructor is NOT virtual!
~Base()
{
delete print_on_destruct_;
}
protected:
PrintOnDestruct* print_on_destruct_;
};
// the NonVirtualDerived class, doesn't have a virtual destructor either
class NonVirtualDerived : public Base
{
public:
NonVirtualDerived()
: Base()
{
print_on_destruct_child_ = new PrintOnDestruct( "NonVirtualDerived" );
}
// the destructor is NOT virtual!
~NonVirtualDerived()
{
delete print_on_destruct_child_;
}
protected:
PrintOnDestruct* print_on_destruct_child_;
};
// the VirtualDerived class does have a virtual destructor
class VirtualDerived : public Base
{
public:
VirtualDerived()
: Base()
{
print_on_destruct_child_ = new PrintOnDestruct( "VirtualDerived" );
}
// the destructor is virtual!
virtual ~VirtualDerived()
{
delete print_on_destruct_child_;
}
protected:
PrintOnDestruct* print_on_destruct_child_;
};
int main()
{
// create the two child classes
Base* non_virtual_derived = new NonVirtualDerived;
Base* virtual_derived = new VirtualDerived;
// delete the two objects
delete non_virtual_derived; // works as expected (only calls Base's destructor, the memory of NonVirtualDerived will be leaked)
delete virtual_derived; // segfault, after calling Base's destructor
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我原本期望程序输出以下两行并正常退出:
Destructing: Base
Destructing: Base
Run Code Online (Sandbox Code Playgroud)
我得到了那个输出,但是在第二行之后,程序退出并出现了分段错误.并且消息:
*** Error in `...': free(): invalid pointer: 0x00000000006020e8 ***
Run Code Online (Sandbox Code Playgroud)
我已经改变了两个调用的顺序delete
,但是程序总是会在调用中发生段错误delete virtual_derived;
.谁能告诉我为什么会这样?
答案真的在于声明:
Base* virtual_derived = new VirtualDerived;
Run Code Online (Sandbox Code Playgroud)
您正在尝试"释放"'malloc'未返回的地址.要了解原因,请将此行替换为
VirtualDerived* x = new VirtualDerived;
Base* virtual_derived = x;
Run Code Online (Sandbox Code Playgroud)
如果您打印这两个地址,您会注意到'x'和'virtual_derived'具有不同的值.'malloc'返回的地址(通过'new')是'x',传递给'free'的地址(通过'delete')是'virtual_derived'.