• C++——多态、虚表、单继承、多继承、覆盖、联编


    目录

    1、多态(4种) 

    2、虚函数的运行原理

    3、单继承 

    4、多继承

    5、 覆盖(重写)的条件

    6、联编 

    1、多态(4种) 

            定义:就是多种形态,具体点就是去完成某个行为,当不同的对象去完成时会产生出不同的状态。会使程序变得更简单。

    ①多态的形式:

    (1)重载多态——函数重载——运算符重载
    (2)包含多态——virtual函数
    (3)参数多态——模板
    (4)强制多态——强制类型转换(有四种) static_cast const_cast...

    ②多态的条件:
    (1)满足覆盖
    (2)基类的指针或者引用指向基类对象或派生类对象

    2、虚函数的运行原理

    • 如果一个类包含了虚函数,不管有多少个虚函数,则只增加一个指针的大小;
    • 有了一个VPtr(虚指针),VPtr指向一个虚表(vtable),虚表里面存储本类中虚函数的入口地址(可以把表格当成一个数组);
    • 非虚函数1个字节,虚函数4个字节(当前一个指针的大小)。
    1. class A
    2. {
    3. public:
    4.     //void ff() {}//非虚函数1个字节,虚函数4个字节(当前一个指针的大小)
    5.     virtual void fa() { cout << "A::fa" << endl; }
    6.     virtual void fb() { cout << "A::fb" << endl; }
    7.     virtual void fc() { cout << "A::fc" << endl; }
    8. };
    9. int main()
    10. {
    11.     //cout<
    12.     A a;
    13.     typedef void(*FUN)();
    14.     /*a.fa();
    15.     a.fb();
    16.     a.fc();*/
    17.     FUN pf = NULL;//pf是函数指针类型,先指向空
    18.     (int*)(&a);//把a*强转为int*
    19.     pf = (FUN) * ((int*)(*(int*)(&a)));
    20.     pf();
    21.     pf = (FUN) * ((int*)(*(int*)(&a))+1);
    22.     pf();
    23.     pf = (FUN) * ((int*)(*(int*)(&a))+2);
    24.     pf();
    25.     
    26. }

    3、单继承 

    • A可以调用三个虚函数:fa,ga,ha

    1. class A
    2. {
    3. public:
    4. virtual void fa() { cout << "A::fa" << endl; }
    5. virtual void fb() { cout << "A::ga" << endl; }
    6. virtual void fc() { cout << "A::ha" << endl; }
    7. };

    单继承步骤:

    ① 全盘接收:B把A的虚表直接继承,class B : public A。

    ②改写:改写A中的虚函数,改为B::fa。

    ③添加自己的函数:添加了两个自己的虚函数gb,hb。

    注意:子类对象不能接收基类对象,子类对象比较多;

    •  B可以调用5个函数:fa,ga,ha,gb,hb
    1. //B可以调用5个函数:fa,ga,ha,gb,hb
    2. class B :public A//B把A的虚表直接继承过来
    3. {
    4. public:
    5. virtual void fa() { cout << "B::fa" << endl; }//改写A中的虚函数
    6. //添加两个虚函数
    7. virtual void gb() { cout << "B::gb" << endl; }
    8. virtual void hb() { cout << "B::hb" << endl; }
    9. };
    10. int main()
    11. {
    12. //cout<
    13. B b;
    14. typedef void(*FUN)();
    15. FUN pf = NULL;//pf是函数指针类型,先指向空
    16. //先给b取个地址
    17. pf = (FUN) * ((int*)(*(int*)(&b)));//B::fa
    18. pf();
    19. pf = (FUN) * ((int*)(*(int*)(&b)) + 1);//A::ga
    20. pf();
    21. pf = (FUN) * ((int*)(*(int*)(&b)) + 2);//A::ha
    22. pf();
    23. pf = (FUN) * ((int*)(*(int*)(&b)) + 3);//B::gb
    24. pf();
    25. pf = (FUN) * ((int*)(*(int*)(&b)) + 4);//B::hb
    26. pf();
    27. }

    4、多继承

     多继承:在子类的对象中,每个父类都有自己的虚表,将最终子类的虚函数放在第一个,
    父类的虚表中,这样做解决了不同的父类类型的指针指向比较清晰。
    如果在子类中重写了多个父类的同名同参虚函数,那么在虚表中同样做了修改。

    1. class A
    2. {
    3. public:
    4. virtual void ff() { cout << "A::ff" << endl; }
    5. virtual void ha() { cout << "A::ha" << endl; }
    6. };
    7. class B
    8. {
    9. public:
    10. virtual void ff() { cout << "B::ff" << endl; }
    11. virtual void hb() { cout << "B::hb" << endl; }
    12. };
    13. class C
    14. {
    15. public:
    16. virtual void ff() { cout << "C::ff" << endl; }
    17. virtual void hc() { cout << "C::hc" << endl; }
    18. };
    19. //D继承了三个虚表,谁先继承就挂谁(内存里面)
    20. class D:public A,public B,public C
    21. {
    22. public:
    23. virtual void ff() { cout << "D::fd" << endl; }
    24. virtual void hd() { cout << "D::hd" << endl; }
    25. };
    26. int main()
    27. {
    28. cout << sizeof(D) << endl;//12
    29. D d;
    30. typedef void(*FUN)();
    31. FUN pf = NULL;//pf是函数指针类型,先指向空
    32. pf = (FUN) * ((int*)*(int*)(&d));//
    33. pf();
    34. pf = (FUN) * ((int*)*(int*)(&d) + 1);//
    35. pf();
    36. pf = (FUN) * ((int*)*(int*)(&d) + 2);//
    37. pf();
    38. cout << "第二张虚表" << endl;
    39. pf = (FUN) * ((int*)*(int*)(&d) + 3);//
    40. pf();
    41. pf = (FUN) * ((int*)*(int*)((int*)(&d)+ 1));//
    42. pf();
    43. pf = (FUN) * ((int*)*(int*)((int*)(&d) + 1)+1);//
    44. pf();
    45. pf = (FUN) * ((int*)*(int*)((int*)(&d) + 1)+2);//
    46. pf();
    47. }

    5、 覆盖(重写)的条件

    覆盖(重写):是指同名同参的函数。

    • 最少两个类,必须是父子关系
    • 必须是同名同参虚函数,基类写了virtual虚函数,子类里可以不写(子类继承)

    6、联编 

    (1)定义:

             联编:是指计算机程序彼此关联的过程,(使一个源程序经过编译、连接,成为一个可执行程序)的过程;在这个联编过程中,需要确定程序中的操作调用(函数调用)与执行该操作函数)的代码段之间的映射关系。

    (2)分类:

    •     静态联编(是早期绑定)
    •      动态联编

    联编(捆绑,绑定)——函数调用和函数体联系的过程
    早捆绑——在编译时
    挖捆绑——在运行时 

    1. class A
    2. {
    3. public:
    4. virtual void fn() { cout << "A::fn" << endl; }
    5. virtual void ff() { cout << "A::ff" << endl; }
    6. void fff() { cout << "A::fff" << endl; }
    7. };
    8. class B :public A//B把A的虚表直接继承过来
    9. {
    10. public:
    11. virtual void fn() { cout << "B::fn" << endl; }//改写A中的虚函数
    12. virtual void fb() { cout << "B::fb" << endl; }
    13. void fff() { cout << "A::fff" << endl; }
    14. };
    15. void test1(A* p)
    16. {
    17. p->fn();
    18. }
    19. void test(A& aa)
    20. {
    21. aa.fn();
    22. aa.ff();
    23. aa.fff();
    24. }
    25. int main()
    26. {
    27. A a;
    28. B b;
    29. test(a);
    30. test(b);
    31. test1(&a);
    32. test1(&b);
    33. }

    如有错误,敬请指正。

    您的收藏与点赞都是对我最大的鼓励和支持!

  • 相关阅读:
    解决pycharm安装opencv没有函数提醒的问题
    【LeetCode-中等题】40. 组合总和 II
    DTDX991A 61430001-UW 自由IOT引入人工智能功能
    Unity DropDown 组件 详解
    BSV 上的信息不完整游戏
    uni-app父子组件传递数据(更新中)
    力扣每日一题 6/20 数学+数组
    Linux内网渗透基础篇
    2018年美亚杯电子数据取证大赛-团体赛
    【python爬虫】10.指挥浏览器自动工作(selenium)
  • 原文地址:https://blog.csdn.net/x20020402/article/details/128043032