C++多态:纯虚函数和抽象类、虚析构和纯虚析构

张开发
2026/4/14 4:12:30 15 分钟阅读

分享文章

C++多态:纯虚函数和抽象类、虚析构和纯虚析构
1、纯虚函数和抽象类在之前发布的博客《深度剖析C中多态的原理》一文中已经提到了多态的概念即不同的对象去完成某个行为时会产生不同的状态。因此在多态中通常父类中虚函数的实现是毫无意义的主要都是调用子类重写的函数因此可以将虚函数改为纯虚函数。纯虚函数语法virtual 返回值类型 函数名 参数列表 0 ;抽象类就是指当一个类中有了纯虚函数或纯虚析构函数时纯虚析构后面会有讲解这个类就称作抽象类。抽象类有以下特点无法实例化对象无论采用何种方式子类必须重写抽象类中的纯虚函数否则也属于抽象类以下时代码示例读者可自行运行查看#includeiostream using namespace std; class Base { public: virtual void func() 0; }; class Son :public Base { public: virtual void func() { cout func调用 endl; }; }; void test01() { //Base base;错误示例抽象类无法实例化对象 Base* base NULL; //base new Base;错误示例抽象类无法实例化对象 base new Son;//在堆区初始化一个Son类的对象用base指对其进行维护 base-func(); delete base;//记得销毁 } int main() { test01(); system(pause); return 0; }2、虚析构和纯虚析构在使用多态时如果子类中有属性开辟到堆区那么父类指针在释放时无法调用到子类的析构代码此时就用到了虚析构函数只需将父类中的析构函数改为虚析构函数或者纯虚析构函数就可以解决父类指针无法释放子类对象的问题。虚析构和纯虚析构的相同之处可以解决父类指针释放子类对象的问题都需要有具体的函数实现虚析构和纯虚析构的不同之处如果是纯虚析构该类属于抽象类无法实例化对象虚析构语法virtual ~类名(){}纯虚析构语法 virtual ~类名() 0;类名::~类名(){}在纯虚析构语法中黄色字体部分在类外实现以下为代码示例class Animal { public: Animal() { cout Animal的构造函数 endl; } //虚析构 /*virtual ~Animal() { cout Animal的析构函数 endl; }*/ virtual ~Animal() 0;//纯虚析构函数 virtual void speak() 0; }; //类外实现纯虚析构函数 Animal:: ~Animal() { cout Animal的纯虚析构函数 endl; }注无论是虚析构函数还是纯虚析构函数都必须有具体的函数实现因为父类中可能也有属性开辟到堆区需要调用析构函数来释放堆区数据下面通过代码运行结果来说明虚析构或纯虚析构的作用#includeiostream using namespace std; #includestring class Animal { public: Animal() { cout Animal的构造函数 endl; } //虚析构 /* virtual ~Animal() { cout Animal的析构函数 endl; }*/ virtual ~Animal() 0;//纯虚析构需要声明也需要实现 //和包含普通纯虚函数的类一样包含了纯虚析构函数的类也是一个抽象类。不能够被实例化。 virtual void speak() 0; }; Animal:: ~Animal() { cout Animal的纯虚析构函数 endl; } class Cat :public Animal { public: Cat(string name) { cout cat 的构造函数 endl; m_name new string(name); } ~Cat() { cout cat的析构函数 endl; if (this-m_name ! NULL) { delete m_name; m_name NULL; } } virtual void speak() { cout *m_name小猫在说话 endl; } public: string *m_name; }; void test01() { Animal* animal new Cat(Tom);// 利用父类指针指向子类对象代表多态的发生 animal-speak(); delete animal; } int main() { test01(); system(pause); return 0; }在上述代码中子类Cat中有在堆区存放的成员变量m_name当父类中的析构函数不是虚构函数或纯虚析构函数时delete animal;这条语句是无法释放子类在堆区中的数据的运行结果如下图所示 在图片中可以看到子类的析构函数并未被调用。将父类中的析构函数改为虚析构或纯虚析构函数后父类指针在释放后即执行 delete animal;语句后便可以调用子类的析构函数对子类在堆区中的数据进行释放如下图所示以上就是我学习后总结的知识如有不恰当的部分欢迎指正

更多文章