类与类的关系:有三种
(1)组合:一个对象是另外一个对象的一部分 是一种 has_a的关系
(2)继承:一个对象是另外一个对象的一种 是一种is_a的关系 私有继承是has_a的关系
(3)代理:容器适配器的实现
一:同名函数的关系
1.重载:同作用域同名,参数列表不同
2.隐藏:被隐藏的函数任然存在只是看不见
3.覆盖:不存在
二:基类和派生类的构造顺序:先调用基类的构造函数再调用派生类的构造函数
三:基类的指针或者引用可以指向或者引用派生类对象,但是派生类的指针或引用不可以指向基类对象
四:virtual
1.加virtual关键字之后类中会多出四个字节是一个虚函数指针,指向一个虚表
2.虚函数表中存放的都是虚函数的入口地址
3.基类中是虚函数派生类中同名同参的函数也是虚函数,所以派生类也有虚函数指针指向虚表,但是不管多少个虚函数都只有一个虚函数指针
4.虚函数表的布局:
5.虚表的合并:虚表不合并的话查找效率低(必须把所有虚表遍历一遍)而且占空间,虚表合并时会把派生类的vfptr合并到基类的vfptr,合并规则是沿着继承链合并往基类方向合并,用派生类虚表信息覆盖基类
6.虚函数表在编译期间就确定了,即编译期间已合并,在运行时让vfptr指向(因为运行时才对对象开辟内存才会有vfptr)该表存放在Rodata只读数据段中
7.一个虚表对应的是一个类(因为编译时就确定了虚表,只不过运行时让对象的指针指向虚表,所以一个虚表对应一个类)而不是一个对象,一个类的所有对象对应一个虚表
8.寄存器中的值只有在运行时才能知道
普通函数调用在编译时就确定函数的调用方式称为静态绑定,即静多态
运行时才能知道函数的入口地址的称为动态绑定,即动多态
9.运行时只会加载数据段和指令段不加载符号表,函数入口地址只有在编译链接时才知道而符号表运行时不会加载到内存中,但是rodata段可以在运行时加载到内存中,所以将虚函数入口地址放在只读数据段中