第五章:多态

多态定义:
c++ 支持多态条件:
1. 在继承状态下,父类指针指向子类对象,通过该指针调用虚函数
2. 父类中存在虚函数,且子类中重写了父类的虚函数
重写:在继承条件下,子类定义了一个与父类虚函数一模一样的函数
多态优点:
解决了继承中的问腿,可以通过父类指针准确调用子类中不统一的函数,且无需使用函数指针 虚函数 - 虚函数指针 - 虚函数列表
虚函数:
普通的函数不会占用类的空间,若在空类中创建一个或多个虚函数,类所占的空间则是 4 个字节
虚函数指针:
__vfptr (虚函数指针):在一个类中,当存在虚函数时,在定义对象的内存空间的首地址会多分配出一
块内存,在这块内存中增加一个指针变量(二级指针 void** ),也就是虚函数指针。
注意:
1. 属于类的,在编译期存在,与所有成员共享
2. 必须通过真实存在的对象调用,无对象或者空指针对象无法调用虚函数
虚函数调用流程:
1. 定义对象获取对象内存首地址中的 __vfptr
2. 间接引用找到虚函数指针指向的虚函数列表 vftable
3. 通过下标定位到要调用的虚函数元素(虚函数地址)。
4. 通过这个地址(函数入口地址)调用到了虚函数。

 

虚函数和普通成员函数的区别:
1. 调用流程不同:虚函数的调用流程相比普通成员函数而言复杂得多,这是他们的本质区别。
2. 调用效率不同:普通的成员函数通过函数名(即函数入口地址)直接调用执行函数,效率高速度快,
虚函数的调用需要虚函数指针 - 虚函数列表的参与,效率低,速度慢。
3. 使用场景不同:虚函数主要用于实现多态,这一点是普通函数无法做到的。
多态实现的原理:
前提:
虚函数列表是属于类的,父类和子类都会有各自的虚函数列表, vfptr 属于对象,每个对象都有各自的
_vfptr
原理:
1. 由于子类继承父类,不但继承了父类的成员,还会继承父类的虚函数列表 2. 编译器会检查子类是否重写父类的虚函数,如果重写,子类的虚函数会替换掉父类的虚函数,即覆
盖,覆盖后便指向了子类的虚函数
3. 如果子类没有重写父类的虚函数,父类虚函数会保留在子类的虚函数列表
4. 如果子类定义了独有的虚函数,将其添加到子类的虚函数列表末尾
流程:
class CFather {
public:
virtual void fun1() {
cout << __FUNCSIG__ << endl;
}
virtual void fun2() {
cout << __FUNCSIG__ << endl;
}
};
class CSon :public CFather {
public:
virtual void fun1() {
cout << __FUNCSIG__ << endl;
}
virtual void fun3() {
cout << __FUNCSIG__ << endl;
}
void fun4() {
cout << __FUNCSIG__ << endl;
}
};
int main() {
CFather fa;
CSon son;
//定义(new)哪个子类对象,虚函数指针就会指向哪个类的虚函数列表,与哪个指针无关
CFather* pFa = new CSon; //虚函数指针->子类的虚函数列表(而不是父类)
pFa->fun1(); //void __thiscall CSon::fun1(void)
pFa->fun2(); //void __thiscall CFather::fun2(void)
((CSon*)pFa)->fun3(); //void __thiscall CSon::fun3(void)
return 0;
}

 

虚析构:
问题:
在多态下,父类的指针指向子类的对象,最后在回收空间的时候,是按照父类的类型来回收的,只调用
了父类的析构,子类的析构并没有执行,可能会导致内存泄漏
虚析构解决:
在父类析构函数之前加 ~ 使其变为虚析构时,调用 pFa 析构会发生多态行为,真正调用的是子类析构,最
后回收对象内存空间时,再调用父类的析构
纯虚函数:
在多态下,有时抽象出来的虚函数作为接口函数,并不知道如何实现或者不需要实现,就是为了多态而
生的,只有继承的子类才知道如何实现,可以把父类的虚函数变为纯虚函数
写法: 在一般虚函数后 =0
特点: 当前类不必实现,而子类必须要重写实现父类的纯虚函数,如果父类的纯虚函数没有被重写,
允许 定义子类对象
虚函数实现多态的缺点:
1. 效率问题:调用虚函数效率低,速度慢
2. 空间问题:定义每一个对象都会额外开辟指针大小的空间,虚函数列表占用程序的内存空间,并且会
随着继承的层级递增,占用的空间越来越多
3. 安全问题:通过其他方法可以模拟虚函数的调用,跨过访问修饰符的限制, 私有的函数最好不要变为
虚函数,否则会有安全隐患
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

橙栩源

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值