析构函数

C++多态

帅比萌擦擦* 提交于 2020-02-07 02:15:42
多态用一句话来总述就是:父类的指针或者引用指向基类的对象 多态分为两种: 编译时多态(静态多态):函数重载,运算符重载 运行时多态(动态多态):派生类,虚函数 静态多态:函数地址早绑定 动态多态:函数地址晚绑定 子类在构造前必须先构造父类,再构造子类,析构顺序相反 non-virtual函数:你不希望子类重写这个函数(override) virtual函数:你希望子类重写这个函数,且你已经有了默认定义 pure-virtual函数:你希望子类一定要重写这个函数,且你对它没有默认定义 ①构造函数可以设置为虚函数吗? 1.从存储空间角度。 虚函数对应一个vtable,这个vtable其实是存储在对象的内存空间的。问题出来了,如果构造函数是虚的,就需要通过 vtable来调用,可是对象还没有实例化,也就是内存空间还没有,无法找到vtable,所以构造函数不能是虚函数。 2,从使用角度 构造函数本身就是要初始化实例,那使用虚函数也没有实际意义呀。所以构造函数没有必要是虚函数。虚函数的作用在于通过父类的指针或者引用来调用它的时候能够变成调用子类的那个成员函数。而构造函数是在创建对象时自动调用的,不可能通过父类的指针或者引用去调用,因此也就规定构造函数不能是虚函数。 3、从实现上看,vbtl在构造函数调用后才建立,因而构造函数不可能成为虚函数 ②虚析构函数 如果子类的成员变量有堆区开辟的空间

C++学习笔记3

妖精的绣舞 提交于 2020-02-05 19:09:32
三、类和对象 1、类的概念 类是具有共同性质的一类事物的统称, 而对象是根据抽象的概念实例化出来的一个实际对象 C 结构: 结构体成员是数据; C++中的类: 类的成员是 数据和函数(数据成员、成员函数) 成员的访问权限有: 1) 私有成员: private, 它只能被该结构中的其他成员访问 2) 保护成员: protected 不涉及到派生的时候与 private 一样, 后面会详细讲解 3) 公有成员: public, 即可以被结构中的其他成员访问, 又可以被结构外的其他成员访问 把结构体的struct换成class即成为类的定义 类的数据成员默认访问权限是私有的,类的成员和结构体成员的访问方式一致,都是用点 #include<iostream> using namespace std; class stu{ public : int num; void setAge(int a) { age = a;//即使age在下面定义也可以在上面先使用,C++认为类是一个整体 } int getAge(void) { return age; } private: int age; char name[100]; }; int main() { stu lucy; lucy.num=100; cout << "lucy.num = "<< lucy.num<<endl; lucy

QT_3-坐标系统与对象模型

允我心安 提交于 2020-02-05 15:53:04
QT_3-坐标系统与对象模型 Qt窗口系统 坐标体系 以左上角为原点,X向右增加,Y向下增加 对于嵌套窗口,其坐标是相对于父窗口来说的 QWidget 所有窗口及窗口控件都是从QWidget直接或间接派生出来的 对象模型 在Qt中创建对象的时候会提供一个Parent对象指针,下面来解释这个parent到底是干什么的。 QObject是以对象树的形式组织起来的。 当你创建一个QObject对象时,会看到QObject的构造函数接收一个QObject指针作为参数,这个参数就是 parent,也就是父对象指针。 这相当于,在创建QObject对象时,可以提供一个其父对象,我们创建的这个QObject对象会自动添加到其父对象的children()列表。 当父对象析构的时候,这个列表中的所有对象也会被析构。(注意,这里的父对象并不是继承意义上的父类!) 这种机制在 GUI 程序设计中相当有用。例如,一个按钮有一个QShortcut(快捷键)对象作为其子对象。当我们删除按钮的时候,这个快捷键理应被删除。这是合理的。 QWidget是能够在屏幕上显示的一切组件的父类。 QWidget继承自QObject,因此也继承了这种对象树关系。一个孩子自动地成为父组件的一个子组件。因此,它会显示在父组件的坐标系统中,被父组件的边界剪裁。例如,当用户关闭一个对话框的时候,应用程序将其删除,那么

C++笔记8

回眸只為那壹抹淺笑 提交于 2020-02-05 11:33:18
构造函数和析构函数什么时候被调用 ·构造函数用来初始化的,就是说存储空间已经有了。构造函数不负责盖房子,只是装修房子。 ·析构函数也不是回收者整个对象所占的存储空间,只是在这个对象被操作系统回收之前做一些善后工作。(不拆房子,比如把值钱东西搬走这样) 来源: https://www.cnblogs.com/AirBirdDD/p/12262828.html

C++面试

泪湿孤枕 提交于 2020-02-02 14:31:08
vector中v[i]和v.at(i)的区别 v[5]; //A v.at[5]; //B 如果v非空,A和B没有任何区别。如果v为空,B会抛出std::out_of_range异常。 c++标准不要求vecor<T>::operator[]进行下标越界检查,原因是为了提高效率。如果需要下标越界检查,使用at。但性能会受到影响,因为越界检查增加了性能开销。 vector扩容原理 新增元素:vector通过一个连续的数组存放元素,如果集合已满,在新增数据的时候,就要分配一块更大的内存,将原来的数据复制过来,释放之前的内存,在插入新增的元素; 对vector的任何操作,一旦引起空间重新配置,指向原vector的所有迭代器就都失效了; 初始时刻vector的capacity为0,塞入第一个元素后capacity增加为1; 不同的编译器实现的扩容方式不一样,VS2015中以1.5倍扩容,GCC以2倍扩容 哪些函数不能成为虚函数? 不能被继承的函数和不能被重写的函数。 1.普通函数 2.友元函数 3.构造函数 4.内联成员函数 5.静态成员函数 溢出 1.栈溢出(栈的大小通常是1M-2M) 栈溢出是指函数中的局部变量造成的溢出(注:函数中形参和函数中的局部变量存放在栈上) 栈溢出包含两种情况:1.分配的的大小超过栈的最大值,2.分配的大小没有超过最大值,但是分配的buff比接收buff小

类和结构的区别

时光怂恿深爱的人放手 提交于 2020-02-02 12:15:19
区别如下: 1.存储类型: 结构是值类型 ,存储在栈上。 类是引用类型 ,存储在栈上和堆上,堆上存储真实数据,栈上存储存储地址,修改一个引用的值,另一个相同的引用的值就会发生改变。 2.继承性: 类是可以继承的 ,它可以继承其他的类或者接口,也可以 被继承 ,并且,类的许多特性是通过继承来展现的,要 阻止类的继承 , 必须显示的声明sealed 。 结构没有继承 :它不能继承另一个结构或者类,也不能被继承。也正因为如此, 结构不能有抽象成员 。虽然结构没有明确的用sealed声明,可是结构是隐式的。结构能够继承接口,方法和类继承接口是一样的 3.初始化:类可以在声明的时候初始化,结构不能在申明的时候初始化(不能在结构中初始化字段),否则报错。 4.构造函数:类和结构都有自己默认的构造函数。在类中,一旦我们编写了带参数构造函数,默认构造函数就不存在了。当我们要调用不带参数的构造函数来初始化对象时,我们必须再自己编写一个不带参数的构造函数。但是在 结构中,始终存在一个不带参数的默认构造函数 ,并且,这个构造函数是不可替代的,不能重写,也不能覆盖, 在结构中,我们只能编写带参数的构造函数,不能编写不带参数的构造函数 5.析构函数: 类有析构函数,但是结构没有析构函数 6.关键字:在类中可以使用但是在结构中限制使用的关键字有:abstract、sealed、protected

【C++知识】浅谈关于C++的内存管理

巧了我就是萌 提交于 2020-02-01 16:39:08
浅谈关于C++的内存管理 目录 浅谈关于C++的内存管理 1、内存管理的预备工具 malloc/free函数 new/delete表达式 array new/array delete placement new allocator分配器 2、内存管理 1、内存管理的预备工具 malloc/free函数 void* p1=malloc(512); //分配512个字节 free(p1); 对于malloc,它进行分配的内存块,除了需要申请的必要内存空间外,上下各有一个cookie,一共占8个字节,用来记录当前内存块的大小,而整个内存块的大小应该是16的倍数,所以可能还会额外增添一些其他内存空间,所以整个下来,当需要多次申请内存时,就会造成大量的内存空间浪费。 new/delete表达式 complex<int>* p2=new complex<int>; delete p2; new:实际上分为三个步骤:1) 分配内存 ,调用operator new函数,而operator new函数实际上就是调用malloc分配内存;2) 类型转换 ,对于分配内存后返回的变量进行转换成指针类型,因为new需要返回一个指针类型;3) 自动调用构造函数 。 delete:1)自动调用析构函数;2)释放内存,调用operator delete函数,而operator

C++中构造函数、虚函数、析构函数的执行顺序

折月煮酒 提交于 2020-02-01 12:40:02
#include <iostream> using namespace std; class A { public: // 第一步:执行类A的构造函数,输出"构造函数A" A() { cout << "构造函数A" << endl; } virtual void func() { cout << "构造A" << endl; } // 第七步:执行类A的析构函数,输出"析构函数A" ~A() { cout << "析构函数A" << endl; } virtual void fund() { cout << "清除A" << endl; } }; class B : public A { public: // 第二步:执行类B的构造函数,调用类A里虚函数,输出"构造A" B() { func(); } // 第四步:执行主函数里的c.fun(),输出"开始...",并调用func(); // 由于fun()不是构造函数和析构函数,且func()为虚函数 // 所以最终结果输出"开始...类C" void fun() { cout << "开始..."; func(); } // 第六步:执行类B的析构函数,调用fund()函数; // 由于是在析构函数里,且fund()为虚函数,所以执行类A里的fund(); // 输出清除A ~B() { fund(); } }; class C

【博客158】exit(0) 与 return 0 并不总是相等的!

风格不统一 提交于 2020-01-30 02:07:23
内容: 在c语言中,exit(0); 和 return 0; 的差异不是特别的明显,但是在C++中是有区别的 exit(0)与return 0 区别: 1. c++中,编译器会将类析构函数的汇编代码插入到 return 前面,但对exit不作任何变动。 return 会自动 调用对象的析构函数 , 而exit不会 2. exit是系统调用级别的,它表示了一个进程的结束,它将收回进程使用的内存空间,同时把错误信息返回 exit ( 0 ) 表示程序正常 , exit ( 1 ) 和 exit ( - 1 ) 表示程序异常退出, exit ( 2 ) 表示系统找不到指定的文件。在 整个程序中,只要调用exit就结束。 3. return 是语言级别的,它不仅会完成进程的清理工作,同时还会完成语言特定的清理工作,还会配合完成 特定语言的清理动作,比如在 return 前面插入C ++ 的析构函数的代码 测试实例: 1.使用return则程序结束时会调用析构 2.使用exit(0)则程序结束不会调用析构 大四学生一枚,文章均非抄袭或者模仿,均为原创,仅代表个人观点,如果文章有错误的地方,欢迎在下方提出,每条评论我都会去认真看并回复,同时感谢指正的前辈。 来源: CSDN 作者: 想成为大程序员的小程序员 链接: https://blog.csdn.net/qq_43684922

析构函数的作用及合成析构函数

断了今生、忘了曾经 提交于 2020-01-29 21:48:49
转载自大佬的blog:https://blog.csdn.net/richard_rufeng/article/details/17035821 析构函数 用于释放在构造函数或在对象生命期内获取的资源。 如果类需要析构函数,那么也需要复制操作符和复制构造函数。 何时调用析构函数? 当对象的引用或指针超出作用域时,不会运行析构函数,只有删除指向动态分配对象的指针或实际对象(而不是对象的引用)超出作用域时,才会运行析构函数。 合成析构函数: 编译器总是为我们合成一个析构函数,合成析构函数按对象创建时的逆序撤销每个非static成员,对于类类型的成员,合成析构函数调用该成员的析构函数来撤销对象。 析构函数是在类名字前加~,没有返回值,没有形参,不能重载析构函数,我们可以为一个类定义多个构造函数,但只能提供一个析构函数 析构函数和构造函数的一个不同是,即使你定义了析构函数,合成析构函数也会运行。 来源: CSDN 作者: 多行不译必自闭 链接: https://blog.csdn.net/dajiangyou123456/article/details/104109600