既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
父类定义:A(int a) {}
那么子类则麻烦一点,定义时需要把父类带上即:B():A(1) {} 或者子类也有参数 B(int a):A(a) {} (这个地方随便传进去一个值就行)
上面大概讲了一下关于构造函数的问题,接下来讲解为何一定要使用虚析构函数:
一,正常的定义方式就是某个类定义出对应类的方法即:
父类定义父类对象,子类定义子类对象。这个时候调用函数以及析构都是正常的:
eg(代码在最后):
父类初始化父类对象和子类初始化子类对象运行截图:
因为子类会调用父类的构造函数,所以B对象b时会有父类的构造函数和析构函数出现;
二,当父类用子类初始化自己对象时(即C++中多态的实现)
此时析构函数和虚析构函数就会有区别,看运行截图
可以看出第一种使用非虚析构函数时,调用了子类的构造函数,但是却没有析构,因此就会造成内存泄漏。
重点:
为什么会产生这种原因呢,是因为使用virtual时,会生成虚函数表,即对象调用参数时会参考这个虚函数表。
比如父类A中有show()函数,子类中也有show()函数:那么如果父类定义时使用了virtual,那么虚函数表中就会保存一个指向子类中show()函数的指针。
假如父类为School,子类为Class。类中都有函数show();
那么School *test = new Class后。会执行test->show;和delete test;的操作。
一,如果test和析构两个都不是虚函数
那么执行的时候,首先查看虚函数表里,但是此时虚函数表里什么也没有,继续往下找,也就找到了父类的show和析构函数,然后执行。自然子类的析构就不会被调用,且show也是执行父类中。二,如果两个都是虚函数
那么执行的时候,虚函数表里两个都有:
- 当执行show函数时,会从虚函数表里会找到指向子类show函数的指针,因此就会执行子类的函数;
- 然后执行析构函数,先从虚函数表里找到了子类的析构函数,执行完发现没有释放掉对象test,继续找虚函数表,但是找完也没有释放对象test,然后从父类中找,找到析构函数后执行,此时就释放了对象test,程序也就结束了。
因此也就明白了为什么会如果析构函数不定义为虚析构,那么可能就不会执行子类的析构函数,也就会产生图一中的情况。
代码:
#include<iostream>
using namespace std;
class A{
public:
A(){ cout << "调用A的默认构造函数" << endl; }
virtual ~A(){ cout << "调用A的析构函数" << endl; }
};
class B:public A{
public:
B(){ cout << "调用B的默认构造函数" << endl; }
~B(){ cout << "调用B的析构函数" << endl; }
};
int main()
{
/*
//实验一
cout << "A对象a::" << endl;
A *a = new A();
delete a;
cout << endl << endl;
cout << "B对象b::" << endl;
B *b = new B();
delete b;
*/
![img](https://img-blog.csdnimg.cn/img_convert/c6e090c56ce359f3757cb98cdceab356.png)
![img](https://img-blog.csdnimg.cn/img_convert/ad88ad08a4e7efb31986a85809eb8dbf.png)
**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!**
**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**
**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618668825)**
发知识点,真正体系化!**
**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**
**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618668825)**