多态(1)—— 多态的定义、多态的三个必要条件、静态联编和动态联编、虚析构函数、重载重写重定义

1、多态的意义

  如果有几个上似而不完全相同的对象,有时人们要求在向它们发出同一个消息时, 它们的反应各不相同,分别执行不同的操作。这种情况就是多态现象。

  C++中所谓的多态(polymorphism)是指,由继承而产生的相关的不同的类,其对象对同一消息会作出不同的响应。

2、多态的三个必要条件

  • 要有继承
  • 要有虚函数重写
  • 要有父类指针(父类引用)指向子类对象
#include <iostream>
#include <string>
using namespace std;

class Yuebuqun
{
public:
    Yuebuqun(string kongfu)
    {
        this->kongfu = kongfu;
    }
    virtual void fight()//表示修饰一个成员方法是一个虚函数,必要条件2
    {
        cout << "岳不群" << "使用了" << this->kongfu << endl;
    }

    string kongfu;
};

//林平之继承了岳不群
class Linpingzhi :public Yuebuqun
{
public:
    Linpingzhi(string kongfu) :Yuebuqun(kongfu)
    {
    }

    //如果说父类中有一个虚函数是fight(),子类如果去重写这个虚函数,
    //那么如果传递进来的是子类,调用子类的fight,如果传递进来的是父类,调用父类的fight
    void fight()//必要条件2
    {
        cout << "林平之" << "使用了" << kongfu << endl;
    }
};

//令狐冲继承了岳不群
class Linghuchong :public Yuebuqun
{
public:
    Linghuchong(string kongfu) :Yuebuqun(kongfu)
    {
    }

    void fight()
    {
        cout << "令狐冲" << "使用了" << kongfu << endl;
    }
};

//在全局提供一个打斗的方法
void fightPeople(Yuebuqun *hero)//必要条件3,相当于Yuebuqun *hero = xiaopp;或Yuebuqun *hero = xiaoyy;
                                //或Yuebuqun *hero = xiaoll;
{
    hero->fight();//希望如果传递进来的是子类,调用子类的fight;
                  //如果传递进来的是父类,调用父类的fight
                  //这种行为就是多态行为
}

//多态发生的三个必要条件:
//1.要有继承
//2.要有虚函数重写
//3.父类指针或引用指向子类对象
int main(void)
{
    Yuebuqun *xiaoyy = new Yuebuqun("葵花宝典");
    xiaoyy->fight();

    Linpingzhi *xiaopp = new Linpingzhi("辟邪剑谱");
    xiaopp->fight();

    Linghuchong *xiaoll = new Linghuchong("独孤九剑");
    xiaoll->fight();

    //多态的实现
    fightPeople(xiaoyy);//岳不群使用了葵花宝典
    fightPeople(xiaopp);//林平之使用了辟邪剑谱
    fightPeople(xiaoll);//令狐冲使用了独孤九剑
    //编译器默认做了一个安全的处理,编译认为不管传递时子类对象还是父类对象,
    //如果统一执行父类的方法,那么一定可以被成功执行。

    delete xiaoyy;
    delete xiaopp;
    delete xiaoll;

    return 0;
}

 3、静态联编和动态联编

(1)联编是指一个程序模块、代码之间互相关联的过程。

(2)静态联编,是程序的匹配、连接在编译阶段实现,也称为早期匹配。重载函数使用静态联编。

(3)动态联编是指程序联编推迟到运行时进行,所以又称为晚期联编(迟邦定)。switch语句和if语句是动态联编的例子。

1、C++与C相同,是静态编译型语言;
2、在编译时,编译器自动根据指针的类型判断指向的是一个什么样的对象;所以编译器认为父类指针指向的是父类对象;
3、由于程序没有运行,所以不可能知道父类指针指向的具体是父类对象还是子类对象,从程序安全的角度,编译器假设父类指针只指向父类对象,因此编译的结果为调用父类的成员函数。这种特性就是静态联编;
4、多态的发生是动态联编,实在程序执行的时候判断具体父类指针应该调用的方法。

 4、虚析构函数

  • 构造函数不能是虚函数。建立一个派生类对象时,必须从类层次的根开始,沿着继承路径逐个调用基类的构造函数。
  • 析构函数可以是虚的。虚析构函数用于指引delete运算符正确析构动态对象。

5、重载重写重定义

重载(添加)
a、相同的范围(在同一个类中)
b、函数名字相同
c、参数不同
d、virtual可有可无
重写(覆盖) 是指派生类函数覆盖基类函数,特征是:
a、不同的范围,分别位于基类和派生类中
b、函数名字相同
c、参数相同
d、基类函数必须有virtual关键字
重定义(隐藏) 是指派生类的函数屏蔽了与其同名的基类函数,规则如下:
a、如果派生类的函数和基类的函数同名,但是参数不同,此时,不管有无virtual,基类的函数被隐藏。
b、如果派生类的函数与基类的函数同名,但是参数也相同,但是基类函数没有virtual关键字,此时,基类的函数被隐藏。
原文地址:https://www.cnblogs.com/yuehouse/p/9845373.html