• c++多态


    目录

    多态的概念

    多态实现计算器案例

    c++如何实现动态绑定

    纯虚函数和抽象类

    纯虚函数和多继承

    虚析构函数

    虚析构函数作用

    纯虚析构函数

    重载 重定义 重写


    多态的概念

    多态:一种接口,多种形态

    静态多态:如果函数的调用,在编译阶段就可以确定函数的调用地址,并产生代码,就是静态多态(编译时多态)

    动态多态:调用地址不能编译不能在编译期间确定,而需要在运行时才能决定,这这就属于晚绑定(动态多态,运行时多态)

    发生多态的四个条件:

            父类中有虚函数

            必须发生继承

            子类必须重写虚函数(函数名 参数 返回值一致 函数的内容可以不一致)

            父类的指针或引用指向子类的对象

    1. #include
    2. using namespace std;
    3. class Animal
    4. {
    5. public:
    6. virtual void speak()
    7. {
    8. cout << "动物在说话" << endl;
    9. }
    10. };
    11. class Dog:virtual public Animal
    12. {
    13. public:
    14. //重写虚函数 函数的返回值 参数 函数名一样
    15. void speak()
    16. {
    17. cout << "狗在说话" << endl;
    18. }
    19. };
    20. class Cat:virtual public Animal
    21. {
    22. public:
    23. //重写虚函数 函数的返回值 参数 函数名一样
    24. void speak()
    25. {
    26. cout << "猫在说话" << endl;
    27. }
    28. };
    29. //如果两个类发生了继承 父类和子类编译器都会自动转换 不需要人为转换
    30. void do_work(Animal &obj)//多态接口 一个函数实现不同功能
    31. {
    32. obj.speak();//地址早绑定->加上函数前面加上virtual 地址晚绑定
    33. }
    34. void test01()
    35. {
    36. Animal p1;
    37. do_work(p1);//动物
    38. Dog p2;
    39. do_work(p2);//狗
    40. Cat p3;
    41. do_work(p3);//猫
    42. }
    43. int main()
    44. {
    45. test01();
    46. return 0;
    47. }

    多态实现计算器案例

    1. #include
    2. using namespace std;
    3. class Calc
    4. {
    5. public:
    6. virtual int mycalc(int a,int b)
    7. {
    8. return 0;
    9. }
    10. };
    11. class Add:public Calc
    12. {
    13. public:
    14. int mycalc(int a,int b)
    15. {
    16. return a + b;
    17. }
    18. };
    19. class Mul:public Calc
    20. {
    21. public:
    22. int mycalc(int a,int b)
    23. {
    24. return a * b;
    25. }
    26. };
    27. class Sub:public Calc
    28. {
    29. public:
    30. int mycalc(int a,int b)
    31. {
    32. return a - b;
    33. }
    34. };
    35. int do_calc(int a,int b,Calc &obj)
    36. {
    37. return obj.mycalc(a,b);
    38. }
    39. void test01()
    40. {
    41. Add p1;
    42. cout << do_calc(3,4,p1) << endl;
    43. Mul p2;
    44. cout << do_calc(3,4,p2) << endl;
    45. Sub p3;
    46. cout << do_calc(3,4,p3) << endl;
    47. }
    48. int main()
    49. {
    50. test01();
    51. return 0;
    52. }

    c++如何实现动态绑定

    为什么可以根据传入对象的不同来执行不同的语句?

    纯虚函数和抽象类

    纯虚函数:将虚函数等于0 实质是将虚函数 表的函数入口设为NULL

    抽象类:一个类如果有纯虚函数,那么这个类就是一个抽象类,抽象类不能实例化对象

    继承抽象类的子类也是一个抽象类,如果子类重写了虚函数,那么子类就不是抽象类

    1. class Calc
    2. {
    3.     public:
    4.         virtual int mycalc(int a,int b) = 0;//虚函数等于0 纯虚函数
    5. };
    6. class Mob:public Calc
    7. {
    8.     public:
    9.        //子类继承了抽象类 子类也是抽象类
    10. //如果子类重写虚函数 就不是抽象类
    11. };
    12. //如果有纯虚函数的类 叫做抽象类 抽象类无法实例化对象
    13. void test()
    14. {
    15. //Cacl p;//错误
    16. Mod p1;
    17. }

    纯虚函数和多继承

    多继承带来了一些争议,但是接口继承可以说一种毫无争议的运用了。
    绝大数面向对象语言都不支持多继承,但是绝大数面向对象对象语言都支持接口的概念, c++ 中没有接口的概念, 但是可以通过纯虚函数实现接口。
    接口类中只有函数原型定义,没有任何数据定义。
    多重继承接口不会带来二义性和复杂性问题。接口类只是一个功能声明,并不是功能实现,子类需要根据功能说 明定义功能实现。
    注意 : 除了析构函数外,其他声明都是纯虚函数。

    虚析构函数

    虚析构函数作用

    在调用基类的析构函数之前,先调用子类的析构函数

    1. #include
    2. using namespace std;
    3. class Animal
    4. {
    5. public:
    6. virtual void speak()
    7. {
    8. cout << "动物在说话" << endl;
    9. }
    10. virtual ~Animal()
    11. {
    12. cout << "动物的析构" << endl;
    13. }
    14. };
    15. class Dog:virtual public Animal
    16. {
    17. public:
    18. //重写虚函数 函数的返回值 参数 函数名一样
    19. void speak()
    20. {
    21. cout << "狗在说话" << endl;
    22. }
    23. ~Dog()
    24. {
    25. cout << "狗的析构" << endl;
    26. }
    27. };
    28. class Cat:virtual public Animal
    29. {
    30. public:
    31. //重写虚函数 函数的返回值 参数 函数名一样
    32. void speak()
    33. {
    34. cout << "猫在说话" << endl;
    35. }
    36. };
    37. //如果两个类发生了继承 父类和子类编译器都会自动转换 不需要人为转换
    38. void do_work(Animal &obj)//多态接口 一个函数实现不同功能
    39. {
    40. obj.speak();//地址早绑定->加上函数前面加上virtual 地址晚绑定
    41. }
    42. void test01()
    43. {
    44. Animal *p = new Dog;
    45. p->speak();//调用狗的speak
    46. delete p;//加virtual 调用动物的析构 加virtual之后先调用狗的析构 再调用动物的析构
    47. }
    48. int main()
    49. {
    50. test01();
    51. return 0;
    52. }

    纯虚析构函数

    虚构函数等于零

    class Animal
    {
        public:
            virtual void speak()
            {
                cout << "动物在说话" << endl;
            }
            virtual ~Animal() = 0;//
    };

    重载 重定义 重写

    重载:

            函数名相同

            同一个作用域

            参数的个数、顺序、类型不一致

            const也可以成为重载的条件

    重定义:

            发生继承

            子类和父类有同名的变量和函数,父类中同名的变量和函数会被隐藏

    重写:

            父类中有虚函数

            发生了继承

            子类重写了虚函数

            函数名返回值参数一致,函数体不一致

  • 相关阅读:
    ESP32-IDF使用I2S驱动MAX98375--解析WAV文件
    Python学习笔记第二十九天(N维数组(ndarray))
    Cocos2dx 安装运行
    【学习】TensorFlow2环境配置
    理想之光不灭
    Web前端高级课程:深入探索与技能飞跃
    科研DBCO-PEG-NIR-dyes|二苯并环辛炔-聚乙二醇-近红外染料|DBCO-PEG-近红外染料
    高级同步机制:Phaser与CountDownLatch详解
    ArcGIS操作(四)
    .Net6 部署到IIS示例
  • 原文地址:https://blog.csdn.net/2301_77164542/article/details/132915017