各位好友, 本期继续推进 继承下, 多态 !
——>Override ~~ Final (C++11)
(a). Final :修饰虚函数, 表示该虚函数不能被 /重写 ;
(b). Override : 检查派生类是否构成 /重写基类的 /某一个虚函数, 如果没有,重写 /编译会报错 。
——->实现环节 :>
//----->C++ 11
//----->演示__Final
#include
using std :: cout;
using std :: endl;
class Fruits
{
public:
virtual void Price() final {cout
——->NO a .
——->NO b.
——>设计出不想被继承的类, 如何设计 ?
——>方法 一 :基类构造函数私有化 (C++98)—->方法 二 : 基类加一个 “final”(C++11)
——>重载 / 重写 / 重定义—>三者比较 :>
——>接口继承 ~~ 实现继承
——>普通函数的继承是一种实现继承, 派生类继承 /基类函数(可以使用的函数)继承 /函数实现 。
而虚函数 /继承是一种接口继承, 派生类 /继承的 /是基类虚函数的接口, 重写之后 ,进而实现多态;
一般而言, 如果不实现多态, 避免将函数定义成 /虚函数 。
各位好友, 下面__开战 多态原理 !先从 一道经典题入手 !
—–>如下 :>
//一道常见面试题
//
class Base
{
public:
virtual void Func1()
{
cout
为了好友们, 有更好的观感体验, 现附上 彩色 代码图样 :>
———>运行调试 :>
———>内存调用 :>
———>符合多态 :
———>底层汇编 :>
———>不符合多态 :
———>底层汇编 :>
———>探究 /引用 /指针切片 / 差异性 :>
//对象引用 与指针切片 ----->差异
//
#incluide
using std ::cout;
using std :: endl;
class Person
{
public:
virtual void _BuyTicket() const {cout
———>引用切片 :>
———>指针切片 :>
多态是如何用 /虚函数表指针 /指向 /派生类去调用派生类对象, 指向 /基类会去调用基类对象 ?
指针服务器托管网 /指向基类, 去调用 基类对象地址 ;指向派生类,去调用 派生类对象地址 ;
派生类会将基类虚表 /拷贝下来, 之后, 有一个 /虚函数覆盖(重写)/形成/派生类虚表 。
——>注意 :>
多态情况下, 指针 或者 引用 是服务器托管网不存在 拷贝 /切片的 ;
指针 /指向基类 /会去调用/基类对象, 指向派生类 /会去调用 /派生类里面 /基类 /那一部分,
最终编译器, 进行调用, “看到的”仍然是 /基类那一部分的切片;但是 /由于发生了切片,
P 指针 /指向虚表内 /原先的地址 /就会被覆盖 /重写 ,指针 P 指向基类 /会在 基类虚表内 /寻找 /基类地址 .
——->NO1.
——->NO2.
现 /回顾一下多态 /条件 :>
(1). 虚函数必须进行重写 ;(2). 参数调用必须要 /基类的指针 /引用 ;
然而,参数部分,为什么不能是 /派生类指针 或者 引用 ? 又为什么 /不能是 /基类对象 ?
——–>答案 :>
派生类赋值给基类对象 /要切片, 不会拷贝虚表 ;
如果 /基类对象可以赋值给派生类,必须要拷贝虚表 ; 基类虚表中, 是派生类 /还是基类就不确定了 。
当 /虚表拷贝之后, 会出现__基类虚表指针 /调用对象 /不再明确, 调用过程/基类 /竟可以调用派生类 。
——–>虚表存储位置 :
——->代码如下 :>
//探究虚表在哪里 ?
//
class Person
{
public:
virtual void _BuyTicket()
{
cout %pn", *((int*)&pp));
printf("虚表2 :> %pn", *((int*)&stu));
return 0;
}
为了方便好友们, 有更好的观感体验, 现附上 彩色 代码图样 :>
———>虚函数重写 :本质上, 重写__虚函数的实现 ;
———>普通函数 /继承, 实际上,是 /实现继承 ; 而对于 /多态继承, 实际上, 是 /接口继承 。
———->调试 及监视内存窗口 :>
———->验证 :>
//运用函数指针数组的方式
//寻找出 监视窗口隐藏的 Func3()函数
//对象引用 与指针切片 -----》区别 ~~差异
//
#incluide
using std ::cout;
using std :: endl;
class Person
{
public:
virtual void _BuyTicket() const {cout
———>寻找 Func3() 函数 : >
——->小结 :>
——>派生类虚表生成 :
A . 先将基类中 /虚表内容拷贝一份到派生类 /虚表里面 ;
B . 派生类增加 /虚函数,按照 /类中声明的顺序, 依次增加 /派生类虚表 ;
C . 如果, 派生类重写 /基类中 /某一个虚函数, 那么, 派生类虚表 /会去覆盖住 /基类的虚表 。
各位好友, 本期内容, 已完结 !
下一期, 开战 / 新领域—>二叉搜素树(进阶版)“敬请期待!
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
机房租用,北京机房租用,IDC机房托管, http://www.fwqtg.net
本文已收录至GitHub,推荐阅读 Java随想录 微信公众号:Java随想录 原创不易,注重版权。转载请注明原作者和原文链接 目录 Groovy & Java Groovy语法 动态类型 元编程 闭包 运算符重载 控制流 条件语句 循环语句 字符串处…