• 第49课 多态的概念和意义


    1. 函数重写回顾

    (1)父类被重写的函数依然会继承给子类

    (2)子类重写的函数覆盖父类中的函数

    (3)通过作用域分辨符(::)可以访问到父类中的函数

    Child c;
    
     
    
    Parent* p = &c;
    
     
    
    c.Parent::print();  //从父类中继承
    
    c.print();          //在子类中重写
    
     
    
    p->print();         //父类中定义

    2. 面向对象中期望的行为

    (1)根据实际的对象类型判断如何调用重写函数

    (2)父类指针(引用

      ①指向父类对象时,则调用父类中定义的函数

      ②指向子类对象时,则调用子类中定义的重写函数

    3. 面向对象中多态的概念

    (1)根据实际的对象类型决定函数调用的具体目标

    (2)同样的调用语句实际运行时有多种不同的表现形态

        

     

    (3)C++语言直接支持多态的概念

      ①通过使用virtual关键字对多态进行支持

      ②被virtual声明的函数被重写后具有多态特性

      ③被virtual声明的函数叫做虚函数

    【编程实验】多态初体验(可对比第48课的非多态版本)

    #include <iostream>
    
    #include <string>
    
     
    
    using namespace std;
    
     
    
    class Parent
    
    {
    
    public:
    
       
    
        virtual void print()  //多态版本,与48课唯一的不同!
    
        {
    
            cout << "I'm Parent." << endl;
    
        }
    
    };
    
     
    
    class Child : public Parent
    
    {
    
    public:
    
        void print()  //虚函数,父类己加virtual,这里不必再写
    
        {
    
            cout << "I'm Child." << endl;
    
        }
    
    };
    
     
    
    void how_to_print(Parent* p)
    
    {
    
        p->print() ; //展现多态的行为
    
    }
    
     
    
    int main()
    
    {
    
        Parent p;
    
        Child  c;
    
       
    
        //多态,根据实际对象类型来调用虚函数
    
        how_to_print(&p); //I'm Parent.
    
        how_to_print(&c); //I'm Child.
    
      
    
        return 0;
    
    }

    4. 多态的意义

    (1)在程序运行过程中展现出动态的特性

    (2)函数重写必须多态实现否则没有意义

    (3)多态面向对象组件化程序设计的基础特性

    5. 理论中的概念

    (1)静态联编:在程序的编译期间就能确定具体的函数调用(如函数重载

    (2)动态联编:在程序实际运行后才能确定具体的函数调用(如函数重写

    (3)小结

      ①使用父类指针(引用)函数前virtual动态联编没加virtual静态联编

      ②使用父类或子类自身声明对象加不加virtual都是静态联编的

    【实例分析】动态联编静态联编

    #include <iostream>
    
    #include <string>
    
     
    
    using namespace std;
    
     
    
    class Parent
    
    {
    
    public:
    
        virtual void func()
    
        {
    
            cout << "Parent: void func()" << endl;
    
        }
    
     
    
        virtual void func(int i)
    
        {
    
            cout << "Parent: void func(int i): " << i << endl;
    
        }
    
     
    
        virtual void func(int i, int j)
    
        {
    
            cout << "Parent: void func(int i, int j): " << i << ", " << j << endl;
    
        }
    
    };
    
     
    
    class Child : public Parent
    
    {
    
    public:
    
        void func(int i, int j)
    
        {
    
            cout << "Child: void func(int i, int j): " << i << ", " << j << endl;
    
        }
    
     
    
        void func(int i, int j, int k)
    
        {
    
            cout << "Child: void func(int i, int j, int k): " << i << ", " << j << ", " << k << endl;
    
        }
    
    };
    
     
    
    void run(Parent* p)
    
    {
    
        p->func(1, 2);   //展现多态的特性,动态联编
    
    }
    
    int main()
    
    {
    
        Parent p;
    
     
    
        p.func();     //静态联编
    
        p.func(1);    //静态联编
    
        p.func(1, 2); //静态联编
    
     
    
        cout << endl;
    
     
    
        Child c;
    
        c.func(1, 2);   //静态联编
    
     
    
        run(&p);
    
        run(&c);
    
     
    
        cout << endl;
    
     
    
        Parent* p2 = &c;
    
        p2->func();  //动态联编,virtual函数,尽管func()在Child中没有被重写
    
     
    
        return 0;
    
    }

    【编程实验】江湖恩怨

    //场景:庄主打老怪
    
     
    
    #include <iostream>
    
    #include <string>
    
     
    
    using namespace std;
    
     
    
    //老怪
    
    class Boss
    
    {
    
    public:
    
        //无名怪招
    
        int fight()
    
        {
    
            int ret = 10; //威力10
    
           
    
            cout <<"Boss::fight(): " << ret << endl;
    
           
    
            return ret;
    
        }
    
    };
    
     
    
    //老庄主
    
    class Master
    
    {
    
    public:
    
        //八剑齐飞
    
        virtual int eightSwordKill()
    
        {
    
            int ret = 8; //威力10
    
           
    
            cout <<"Master::eightSwordKill(): " << ret << endl;
    
           
    
            return ret;
    
        }
    
    };
    
     
    
    //少庄主
    
    class NewMaster : public Master
    
    {
    
    public:
    
        //八剑齐飞
    
        int eightSwordKill()
    
        {
    
            //少庄主对老庄主的八剑齐飞进行改造,练就了双臂的八剑齐飞
    
            //威力大增
    
            int ret = Master::eightSwordKill() * 2; //威力是老庄主的2倍
    
           
    
            cout <<"NewMaster::eightSwordKill(): " << ret << endl;
    
           
    
            return ret;
    
        }
    
    };
    
     
    
    //战场pk
    
    void field_pk(Master* master, Boss* boss)
    
    {
    
        int k = master->eightSwordKill();
    
        int b = boss ->fight();
    
       
    
        if(k < b)
    
        {
    
            cout <<"Master is killed..." << endl;
    
        }
    
        else
    
        {
    
            cout <<"Boss is killed..." << endl;
    
        }
    
    }
    
     
    
    int main()
    
    {
    
        Master master;
    
        Boss boss;
    
       
    
        cout <<"Master vs Boss" << endl;
    
       
    
        field_pk(&master,&boss);
    
       
    
        cout << endl;
    
       
    
        cout <<"NewMaster vs Boss" << endl;
    
        NewMaster newMaster;
    
       
    
        field_pk(&newMaster, &boss);
    
       
    
        return 0;
    
    }

    /*输出结果

    Master vs Boss

    Master::eightSwordKill(): 8

    Boss::fight(): 10

    Master is killed...

    NewMaster vs Boss

    Master::eightSwordKill(): 8

    NewMaster::eightSwordKill(): 16

    Boss::fight(): 10

    Boss is killed...

    */

    6. 小结

    (1)函数重写只可能发生在父类与子类之间

    (2)根据实际对象的类型确定调用的具体函数

    (3)virtual关键字是C++支持多态的唯一方式

    (4)被重写的虚函数可表现出多态的特性

  • 相关阅读:
    Deadlock Detecting--转
    java.util.concurrent包详细分析--转
    spring源码分析之spring-core总结篇
    Google和Baidu常用的搜索技巧--转
    极速发展的饿了么订单系统架构演进--转
    唯品会订单分库分表的实践总结以及关键步骤--转
    数据扩展性探讨和总结--转
    MAT使用--转
    Java 8 Stream API详解--转
    论海明威的存在主义宗教意识——存在主义虚无主义。注:部分观点个人不赞同
  • 原文地址:https://www.cnblogs.com/hoiday/p/10199940.html
Copyright © 2020-2023  润新知