作用:
发生多态时,若想子类执行其析构行为,需要将父类的析构函数加上virtual关键字变成虚析构函数,这样才能保证在子类对象释放时执行到子类的析构行为
简单概括为:为了解决父类指针释放子类对象问题
父类析构未加virtual关键字:
#include <iostream>
#include <string>
class Animal
{
public:
Animal()
{
std::cout << "Animal构造函数被调用" << std::endl;
}
//普通析构函数
~Animal()
{
std::cout << "Animal析构函数被调用" << std::endl;
}
virtual void Speak() = 0;
};
class Cat :public Animal
{
public:
Cat(std::string& name)
{
m_name = new std::string(name);
std::cout << "Cat构造函数被调用" << std::endl;
}
~Cat()
{
if (m_name != nullptr)
{
delete m_name;
m_name = nullptr;
}
std::cout << "Cat析构函数被调用" << std::endl;
}
virtual void Speak()
{
std::cout << *m_name << "小猫在说话" << std::endl;
}
std::string* m_name;
};
int main()
{
std::string name = "Tom";
Animal* animal = new Cat(name);
animal->Speak();
if (animal != nullptr)
{
delete animal;
animal = nullptr;
}
system("pause");
return 0;
}
父类析构为虚析构:
#include <iostream>
#include <string>
class Animal
{
public:
Animal()
{
std::cout << "Animal构造函数被调用" << std::endl;
}
//虚析构函数
virtual ~Animal()
{
std::cout << "Animal析构函数被调用" << std::endl;
}
virtual void Speak() = 0;
};
class Cat :public Animal
{
public:
Cat(std::string& name)
{
m_name = new std::string(name);
std::cout << "Cat构造函数被调用" << std::endl;
}
~Cat()
{
if (m_name != nullptr)
{
delete m_name;
m_name = nullptr;
}
std::cout << "Cat析构函数被调用" << std::endl;
}
virtual void Speak()
{
std::cout << *m_name << "小猫在说话" << std::endl;
}
std::string* m_name;
};
int main()
{
std::string name = "Tom";
Animal* animal = new Cat(name);
animal->Speak();
if (animal != nullptr)
{
delete animal;
animal = nullptr;
}
system("pause");
return 0;
}
总结:
- 发生多态时,只有父类存在虚析构函数,子类的析构函数才能被执行,否则容易发生内存泄漏。