【C++基础2】

1.C++ 中多态有两种类型:静态多态动态多态
**静态多态通过函数重载实现。**编译时编译器会根据参数判断调用的到底是重载函数的哪个版本。
动态多态通过虚函数实现。
2.虚函数(动态多态是如何实现的)
​当⼀个类中包含虚函数时,编译器会为该类⽣成⼀个虚函数表,保存该类中虚函数的地址,同样,派⽣类继承基类,派⽣类中⾃然⼀定有虚函数,所以编译器也会为派⽣类⽣成⾃⼰的虚函数表。当我们定义⼀个派⽣类对象时,编译器检测该类型有虚函数,所以为这个派⽣类对象⽣成⼀个虚函数指针,指向该类型的虚函数表,这个虚函数指针的初始化是在构造函数中完成的。
后续如果有⼀个基类类型的指针,指向派⽣类,那么当调⽤虚函数时,就会根据所指真正对象的虚函数表指针去寻找虚函数的地址,就可以调⽤派⽣类虚函数表中的虚函数,以此实现多态。
3.构造函数能不能是虚函数?为什么?
不能。一个类中所有虚函数的地址都记录在虚函数表中,类的每个对象都有一个虚函数表指针指向该类的虚函数表,进而能够调用相应的虚函数。调用虚构造函数需要虚表指针,但是虚表指针是在构造函数中初始化的,如果构造函数是虚函数就无法初始化虚表指针。
4.父类的析构函数为什么必须是虚函数
如果不是虚函数的话,指针对象在析构时就无法触发多态,只会调用父类的析构函数,子类的析构函数没有被调用,造成内存泄漏的情况。
5.抽象类
抽象类是指含有纯虚函数的类,纯虚函数没有自己的实现,定义纯虚函数是为了定义一个接口,起到强制规范的作用,规范抽象类的子类必须实现这个函数,否则子类也是一个抽象类。
抽象类不能实例化对象,不仅仅因为他的纯虚函数没有实现,也是因为在大多数情况下,基类本身生成对象是不合理的。例如动物作为基类可以派生出老虎、狮子等子类,但动物本身生成对象明显不合理。所以动物类应该被定义为抽象类,只定义一些纯虚函数作为接口,强制子类实现这些接口。
6.重载和重写(覆盖)的区别
(1)重写是父类和子类之间的垂直关系,重载是不同函数之间的水平关系;
(2)重写要求参数列表相同,重载则要求参数列表不同,返回值不要求;
(3)重写中,实际调用方法根据对象类型决定,重载根据调用时实参表与形参表的对应关系来选择函数体。
7.什么是隐藏?
隐藏指的是,派生类中的函数屏蔽了基类中的同名函数,对参数列表没有要求,可以相同也可以不同。

8.浅拷贝和深拷贝的区别
浅拷贝:**浅拷贝只是拷贝一个指针,并没有新开辟一个地址,拷贝的指针和原来的指针指向同一块地址,如果原来的指针所指向的资源释放了,那么再释放浅拷贝的指针的资源就会出现错误。
深拷贝:**深拷贝不仅拷贝值,还开辟出一块新的空间用来存放新的值,即使原先的对象被析构掉,释放内存了也不会影响到深拷贝得到的值。在自己实现拷贝赋值的时候,如果有指针变量的话是需要自己实现深拷贝的。
9.单例模式设计
单例模式是一种常见的软件设计模式,
核心:只包含一个被称为单例的特殊类。
通过单例模式可以保证系统中一个类只有一个实例,且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源。
本质:类只能实例化一个对象。
10.多继承:可以看作是单继承的扩展。所谓多继承是指派生类具有多个基类,派生类与每个基类之间的关系仍可看作是一个单继承。
11.菱形继承:有公共祖先的继承。
最底层的子类数据会包含多份公共祖先的数据。
12.虚继承:解决菱形继承中多份公共祖先数据的问题。
13.在实现c++多态时会用到虚函数。虚函数使用的其核心目的是通过基类访问派生类定义的函数。所谓虚函数就是在基类定义一个未实现的函数名,为了提高程序的可读性,建议后代中虚函数都加上virtual关键字。(父类指针指向子类空间)
14.重载、重定义、重写的区别
(1)重载:在同一作用域内定义多个同名函数,但要求这些函数具有参数的类型或个数不相同,返回值类型不影响。
(2)重定义:若是在同一作用域内,定义了同名,参数类型和个数也相同的函数,编译时会出现重定义错误。但是若是派生类继承了父类,重新定义了该函数不会报错。而且,不管该函数参数类型是否一致,都会被派生类重定义。
(3)重写:针对多态性,利用同一接口实现不同的实例。若是不声明虚函数,在派生类会重定义基类同名函数。这样便无法实现用基类指针调用派生类函数的目的。
注意:重载一定发生在同一作用域内;重定义发生在基类和派生类中,只要函数名一致就会重定义;重写需要函数名,参数类型一致,基类定义虚函数。测试重载和重定义,重写联合使用的情况。
(1)在基类中重载,在派生类中重定义,派生类对象只能调用派生类中定义了的函数类型,而无法调用从基类继承过来的同名重载函数类型;基类自然是可以调用自身的重载函数。
(2)在基类中不重载,在派生类中重定义+重载,派生类可以调用自己的任何重载函数。
(3)在重写的派生类中重载是不允许的,但是可以在基类中重载虚函数。
15.虚函数和纯虚函数
(1)虚函数,语法:virtual 返回值类型 函数名(参数列表),然后这个类也就变成的虚基类,然后子类重写父类的虚函数。
(2)纯虚函数,语法:virtual 返回值类型 函数名(参数列表)=0,当类中有了纯虚函数,这个类也称为抽象类。
(3)抽象类特点:无法实例化对象抽象类必须被继承子类必须重写父类(抽象类)中所有的纯虚函数,否则也属于抽象类。
抽象类主要的目的是设计类的接口。
(4)虚函数和纯虚函数的区别:
虚函数:virtual修饰,有函数体,不会导致父类为抽象类。
纯虚函数:virtual修饰,=0,没有函数体,导致父类为抽象类,子类表现重写父类所有的纯虚函数。
16.虚析构函数:通过父类指针,释放整个子类空间。
构造的顺序:父类->成员->子类
析构的顺序:子类->成员->父类
17.纯虚析构函数
本质:是析构函数,各个类的回收工作,而且析构函数不能被继承。
纯虚析构函数必须在类内定义, 类外实现。
如果出现了纯虚析构函数,这个类也算抽象类,不可以实例化对象。
18.虚析构和纯虚析构函数的区别:
虚析构:virtual修饰,有函数体,不会导致父类为抽象类。
纯虚析构:virtual修饰,=0,函数体必须在类外实现,导致父类为抽象类。
注意:虚表是在建立构造函数之后建立的,故不能将构造函数设置为虚函数。

你可能感兴趣的:(c++,开发语言)