• C++ 多态


    封装 -> 可读性
    继承 -> 可扩充性
    多态 -> 可重用性

    多态:指同一名字的事物可以完成不同的功能。
    编译时的多态:主要指函数的重载(包括运算符的重载)、对重载函数的调用,在编译时就能根据实参确定应该调用哪个函数,因此叫编译时的多态;
    运行时的多态:和继承和虚函数有关。

    #include <iostream>
    using namespace std;
    
    //基类People
    class People{
    public:
        People(char *name, int age);//声明构造函数 
        void display();
    protected:
        char *m_name;
        int m_age;
    };
    //定义构造函数
    People::People(char *name, int age): m_name(name), m_age(age){}  //构造函数初始化列表 
    void People::display(){
        cout<<m_name<<"今年"<<m_age<<"岁了,是个无业游民。"<<endl;
    }
    
    //派生类Teacher
    class Teacher: public People{
    public:
        Teacher(char *name, int age, int salary);
        void display();
    private:
        int m_salary;
    };
    Teacher::Teacher(char *name, int age, int salary): People(name, age), m_salary(salary){}
    void Teacher::display(){
        cout<<m_name<<"今年"<<m_age<<"岁了,是一名教师,每月有"<<m_salary<<"元的收入。"<<endl;
    }
    
    int main(){
        People *p = new People("王志刚", 23);
        p -> display();
    
        p = new Teacher("赵宏佳", 45, 8200);
        p -> display();
    
        return 0;
    }
    
    
    //运行结果:
    王志刚今年23岁了,是个无业游民。
    赵宏佳今年45岁了,是个无业游民。
    

    发现:当基类指针p指向派生类Teacher的对象时,虽然使用了Teacher的成因变量,但是却没有使用它的成员函数。

    虚函数:让基类指针能够访问派生类的成因函数。

    //更改上面的代码,将display()函数声明为虚函数。
    #include <iostream>
    using namespace std;
    
    //基类People
    class People{
    public:
        People(char *name, int age);//声明构造函数 
        virtual void display();
    protected:
        char *m_name;
        int m_age;
    };
    //定义构造函数
    People::People(char *name, int age): m_name(name), m_age(age){}  //构造函数初始化列表 
    void People::display(){
        cout<<m_name<<"今年"<<m_age<<"岁了,是个无业游民。"<<endl;
    }
    
    //派生类Teacher
    class Teacher: public People{
    public:
        Teacher(char *name, int age, int salary);
        virtual void display();
    private:
        int m_salary;
    };
    Teacher::Teacher(char *name, int age, int salary): People(name, age), m_salary(salary){}
    void Teacher::display(){
        cout<<m_name<<"今年"<<m_age<<"岁了,是一名教师,每月有"<<m_salary<<"元的收入。"<<endl;
    }
    
    int main(){
        People *p = new People("王志刚", 23);
        p -> display();
    
        p = new Teacher("赵宏佳", 45, 8200);
        p -> display();
    
        return 0;
    }
    
    //运行结果:
    王志刚今年23岁了,是个无业游民。
    赵宏佳今年45岁了,是一名教师,每月有8200元的收入。
    
    • 虚函数的作用:构成多态(唯一用处)

      • 基类指针指向基类对象时就使用基类的成员(包括成员函数和成员变量)
      • 基类指针指向派生类对象时就使用派生类的成员。
    • 多态:基类指针可以按照基类的方式来做事,也可以按照派生类的方式来做事,它有多种形态,或者说有多种表现形式,这种现象就是多态。

    • C++多态机制的目的:

      • 可以通过基类指针对所有的派生类(包括直接派生和间接派生)的成员变量和成员函数进行“全方位”的访问。
      • 如果没有多态,就只能访问成员变量。
    • 对象的内存模型是非常干净的,没有包含任何成员函数的信息,编译器是根据什么找到了成员函数? ------> 虚函数表

    • 借助引用也可以实现多态

      • 引用在本质上是通过指针的方式实现的
      • 借助指针可以实现多态,那么就有理由推断,借助引用也可以实现多态。
    #include <iostream>
    using namespace std;
    
    //基类People
    class People{
    public:
        People(char *name, int age);//声明构造函数 
        virtual void display();
    protected:
        char *m_name;
        int m_age;
    };
    //定义构造函数
    People::People(char *name, int age): m_name(name), m_age(age){}  //构造函数初始化列表 
    void People::display(){
        cout<<m_name<<"今年"<<m_age<<"岁了,是个无业游民。"<<endl;
    }
    
    //派生类Teacher
    class Teacher: public People{
    public:
        Teacher(char *name, int age, int salary);
        virtual void display();
    private:
        int m_salary;
    };
    Teacher::Teacher(char *name, int age, int salary): People(name, age), m_salary(salary){}
    void Teacher::display(){
        cout<<m_name<<"今年"<<m_age<<"岁了,是一名教师,每月有"<<m_salary<<"元的收入。"<<endl;
    }
    
    int main(){
    	//实例化对象 
        People p("王志刚", 23);
        Teacher t("赵宏佳", 45, 8200);
        
        
        People &rp = p;
    	People &rt = t; 
    	
    	rp.display();
    	rt.display();
    
        return 0;
    }
    
    
    //运行结果:
    王志刚今年23岁了,是个无业游民。
    赵宏佳今年45岁了,是一名教师,每月有8200元的收入。
    

    由于引用类似于常量,只能在定义的同时初始化,并且以后也要从一而终,不能再引用其他数据,所以本例中一定要定义两个引用变量,
    一个用来引用基类对象,一个用来引用派生类对象。
    从运行结果可以看出,当基类的引用指代基类对象时,调用的是基类的成员,当基类的引用指代派生类对象时,调用的是派生类的成员。

    • 一般谈及多态时是说指针

      • 因为引用不像指针灵活,指针可以随时改变方向,而引用只能指代固定的对象,在多态性方面缺乏表现力。
    • 多态的用途

      • 对于具有复杂继承关系的中大型程序,多态可以增加其灵活性,让代码更具有表现力。
    #include <iostream>
    using namespace std;
    
    //军队
    class Troops{
    public:
        virtual void fight(){ cout<<"Strike back!"<<endl; }
    };
    
    //陆军
    class Army: public Troops{
    public:
        void fight(){ cout<<"--Army is fighting!"<<endl; }
    };
    //99A主战坦克
    class _99A: public Army{
    public:
        void fight(){ cout<<"----99A(Tank) is fighting!"<<endl; }
    };
    //武直10武装直升机
    class WZ_10: public Army{
    public:
        void fight(){ cout<<"----WZ-10(Helicopter) is fighting!"<<endl; }
    };
    //长剑10巡航导弹
    class CJ_10: public Army{
    public:
        void fight(){ cout<<"----CJ-10(Missile) is fighting!"<<endl; }
    };
    
    //空军
    class AirForce: public Troops{
    public:
        void fight(){ cout<<"--AirForce is fighting!"<<endl; }
    };
    //J-20隐形歼击机
    class J_20: public AirForce{
    public:
        void fight(){ cout<<"----J-20(Fighter Plane) is fighting!"<<endl; }
    };
    //CH5无人机
    class CH_5: public AirForce{
    public:
        void fight(){ cout<<"----CH-5(UAV) is fighting!"<<endl; }
    };
    //轰6K轰炸机
    class H_6K: public AirForce{
    public:
        void fight(){ cout<<"----H-6K(Bomber) is fighting!"<<endl; }
    };
    
    int main(){
        Troops *p = new Troops;
        p ->fight();
        //陆军
        p = new Army;
        p ->fight();
        p = new _99A;
        p -> fight();
        p = new WZ_10;
        p -> fight();
        p = new CJ_10;
        p -> fight();
        //空军
        p = new AirForce;
        p -> fight();
        p = new J_20;
        p -> fight();
        p = new CH_5;
        p -> fight();
        p = new H_6K;
        p -> fight();
    
        return 0;
    }
    
    //运行结果:
    Strike back!
    --Army is fighting!
    ----99A(Tank) is fighting!
    ----WZ-10(Helicopter) is fighting!
    ----CJ-10(Missile) is fighting!
    --AirForce is fighting!
    ----J-20(Fighter Plane) is fighting!
    ----CH-5(UAV) is fighting!
    ----H-6K(Bomber) is fighting!
    
  • 相关阅读:
    Silverlight不能调试问题(转摘) Unable to start debugging. Cannot locate Microsoft Internet Explorer.
    Mac OS X 同 Windows 的概念,词汇,热键对比随录,让你更好地过度到Mac OS X
    敏捷度和成熟度
    有什么是安全的吗?
    linux定时任务的设置
    javascript闭包
    (转)JavaScript世界的一等公民 函数
    PHP魔法函数(转)
    JS字符串截取,按字节截取
    linux cp命令
  • 原文地址:https://www.cnblogs.com/xiaobaizzz/p/12333940.html
Copyright © 2020-2023  润新知