c++ | 动态编译|虚函数表|虚函数
c++ 的多态,是c++ 的一大核心特点,也是面向对象思想必须要实现的,不然面向对象也就是没啥光芒? 像 Go 也是有多态这个思想的
c++ 的多态主要有 静态编译多态和动态运行多态
静态编译多态,简单理解就是在编译的时候实现的 多态 。比如重载。注意:c 是没有重载这一说法的
什么是重载?
可以这么理解,重载 对函数、参数列表这种头部啊 入口啊 特别看重,而像出口啊就不态注意了。也好理解,因为编译的时候其实就是匹配,类型匹配啊,并不会去跑一遍,去看看返回什么值啊
这三个 test 函数都是重载,有人将重载是在 class 类中的,但是经过本人测试 在同一作用域 都是可以实现重载的void test(int a);void test(int a, char b);int test(int a);
再讲讲动态多态吧
讲到动态多态,首先就是要讲讲虚函数
虚函数,有纯虚函数,和普通虚函数,纯虚函数是在基类只写一个接口,并没有任何实现(可以理解为是一个空壳)
在派生类中对基类虚函数 重写 会把基类的虚函数 给隐藏 也叫覆盖
派生类通过继承的关系获取基类相应的权限的类成员。
这里再稍微展开讲讲,继承了哪些权限?
默认的类权限访问 是 privated ,继承默认也是 privated 注意 c struct 默认是 public 注意 c++ 的 struct 也可以实现重载、继承 ==> 多态。而c 的 struct 只能封装一些数据类型 ==> 自定义类型
公有继承 ==> 公有部分依然公有访问(注意:基类共有部分只能在派生类类内访问)。protect 保护范围 类内(派生类、基类)访问,什么叫类内访问?就是通过成员方法访问类的成员(这是为了体现封装性,注意啊 谨慎通过类对象对类成员访问,这样其实是破坏了封装性)。privated 私有范围,派生类无法访问,只允许基类类内访问。
protected ==> 公有部分 protected 访问(只能在派生类类内访问通过 protected 继承的public 部分)。protected 部分 protected 访问(只能在派生类类内访问通过 protected 继承的protected 部分)。privated 部分无法访问。
private ==> 公有部分 变成了 private、protected 部分变成了 private,剩下的全部都不可访问。
参考代码
public、protected、private都有哪些权限,各自又有哪些区别
再继续讲讲虚函数表
对了,在讲虚函数表之前,讲讲类的内存分配吧。
类成员会根据声明顺序一次分配内存,如果出现后面一个变量内存小于之前的已分配内存的整数倍,就会填充,如果后面的一个变量内存大雨前面已经分配的内存整数倍也会重新更新类内存分配的整数倍,否则就是按照之前的整数倍去分配。
这个规则和结构体分配内存是一样的。
注意:如果有虚函数,会额外添加一个虚函数表指针 8B
讲的太抽象了?举一个例子说说吧
class Base{
public:virtual void test(){};
private:int a; // 4B [0-3] 当前内存分配的整数倍为 4fload b; //4B [0-3] [4-7] 当前内存分配的整数倍 为 4double c; // 8; [0-3][4-7] [8-11] 当前内存分配的整数倍 为 4char d; //1B [0-3][4-7] [8-11][12-15 13、14、15 均被填充了] 当前内存分配的整数倍 为 4long long e; // 8B [0-3][4-7] [8-11][12-15][16-23] 当前内存分配的整数倍 为 4
};
//注意了,最后还要再分配一个指针大小(指向虚函数表的指针)的内存空间
[0-3][4-7] [8-11][12-15][16-23] [14-31] 当前内存分配的整数倍 为 4
类对象通过虚函数表找到相应的虚函数
参考:虚函数表
参考:虚函数表02
简单自述了一下,cpp的水太深了