先假设这样一个场景,我们声明了一个基类的指针,却绑定了一个派生类的对象。如下面代码所示:
#include <iostream>
class Base
{
public:
Base() {}
~Base() {}
void DoSomething() { std::cout << "Base called." << std::endl; }
};
class Derived : public Base
{
public:
Derived() {}
~Derived() {}
void DoSomething() { std::cout << "Derived called." << std::endl; }
};
int main()
{
Base* p = new Derived();
p->DoSomething(); // Base called.
}在我们未定义虚函数时,程序直接执行了基类的成员函数。析构函数也是如此,我们构建的派生类对象会调用基类的析构函数,可能会造成内存泄漏。如果我们把成员函数改成虚函数,则会这样:
#include <iostream>
class Base
{
public:
Base() {}
~Base() {}
virtual void DoSomething() { std::cout << "Base called." << std::endl; }
};
class Derived : public Base
{
public:
Derived() {}
~Derived() {}
void DoSomething() override { std::cout << "Derived called." << std::endl; }
};
int main()
{
Base* p = new Derived();
p->DoSomething(); // Derived called.
}对象通过查询虚函数表,正确的调用了自己的成员函数。析构函数也会不会这样呢,再做个实验:
#include <iostream>
class Base
{
public:
Base() {}
~Base() { std::cout << "Base deleted." << std::endl; }
};
class Derived : public Base
{
public:
Derived() {}
~Derived() { std::cout << "Derived deleted." << std::endl; }
};
int main()
{
Base* p = new Derived();
delete p; // Base called.
}发现真的只是调用了基类的析构函数,将析构函数换成虚函数:
#include <iostream>
class Base
{
public:
Base() {}
virtual ~Base() { std::cout << "Base deleted." << std::endl; }
};
class Derived : public Base
{
public:
Derived() {}
~Derived() override { std::cout << "Derived deleted." << std::endl; }
};
int main()
{
Base* p = new Derived();
delete p; // Derived deleted.
// Base deleted.
}发现两个析构函数都被成功的调用了,实际上是正确找到了派生类的析构函数,派生类析构函数执行完毕后会再执行基类的析构函数。
因此我们得出结论:在多态中,析构函数最好定义为虚函数。
评论区