C++快速理解之多态

一、多态

1.是什么?
一句话:有多个相同名字的函数,当调用时,会根据调用时的方式不同,调用不同的函数

2.静态多态
以下代码,是一个有2个相同名字,但参数不同函数组成,这样就形成了重载

当调用函数时,到底用哪个,要根据调用时的参数而确定

#include <iostream>

using namespace std;

int Add(int a, int b) {
    cout << "int类型的函数被调用\n";
    return a + b;
}

double Add(double a, double b) {
    cout << "double类型的函数被调用\n";
    return a + b;
}

int main() {
    Add(10, 20);
    Add(10.0, 20.0);
    return 0;
}

在这里插入图片描述

3.动态多态
看下面的代码,f->show()到底调用哪个类中的show函数?

#include<iostream>

using namespace std;

class Father {
public:
    void show() {
        cout << "father show" << endl;
    }
};

class Children : public Father {
public:
    void show() {
        cout << "children  show" << endl;
    }
};

int main() {
    Father *father = new Father();
    father->show();  // 调用父类的show函数

    Children *children = new Children();
    children->show();  // 调用子类的show函数

    Father *p = new Children();
    p->show();  // 调用哪个类中的show函数?

    return 0;
}

在这里插入图片描述
p ->show() 调用 Father的
虽然指向子类,但他是父类型定义的指针变量

通过父类指针去调用成员函数时,编译器只会根据指针的类型(这里是父类指针)来决定调用哪个函数,而不会考虑实际指向的对象类型(这里实际指向的是子类对象)。这种现象称为多态中的静态联编。
如果希望调用子类中重写的函数,需要将父类中的 show 函数声明为虚函数,即 virtual void show() { cout << “father show” << endl; } 。这样就可以实现动态多态性,通过父类指针调用子类重写的函数。

二、virtual
是什么?
可以让一个函数成为虚函数

有什么用?
通过virtual可以实现真正的多态

虚函数可以在父类的指针指向子类对象的前提下,通过父类的指针调用子类的成员函数
这种技术让 父类的指针 或 引用 具备了多种形态,这就是所谓的多态

最终形成的功能:
如果父类指针指向的是一个父类对象,则调用父类的函数
如果父类指针指向的是一个子类对象,则调用子类的函数

怎样用?
定义虚函数非常简单,只需要在函数声明前,加上 virtual 关键字即可
注意:在父类的函数上添加 virtual 关键字,可使子类的同名函数也变成虚函数

例子1:

#include<iostream>

using namespace std;

class Father {
public:
    virtual void show() {
        cout << "father show" << endl;
    }
};

class Children : public Father {
public:
    virtual void show() {
        cout << "children  show" << endl;
    }
};

int main() {
    Father *father = new Father();
    father->show();  // 调用父类的show函数

    Children *children = new Children();
    children->show();  // 调用子类的show函数

    Father *p = new Children();
    p->show();  // 调用哪个类中的show函数?

    return 0;
}

在这里插入图片描述

#include <iostream>

using namespace std;

class WashMachine {
public:
    virtual void wash() {
        cout << "洗衣机在洗衣服" << endl;
    }
};


class SmartWashMachine : public WashMachine {
public:
    virtual void wash() {
        cout << "智能洗衣机在洗衣服" << endl;
    }
};


int main() {
    // 父类指针指向子类对象
    WashMachine *w2 = new SmartWashMachine();
    w2->wash();
    return 0;
}

在这里插入图片描述

以一个开枪过程作例子,逐步深入:
第一案例:
基础版本,冗余的

#include <iostream>

using namespace std;


class MP5 {
public:
    void fire() {
        cout << "开火\n";
        this->push_bullet();
    }

    void push_bullet() {
        // 弹出子弹
        cout << "弹出子弹\n";
    }
};


class AK47 {
public:
    void fire() {
        cout << "开火\n";
        this->push_bullet();
    }

    void push_bullet() {
        // 弹出子弹
        cout << "弹出子弹\n";
    }
};


class Person {
public:
    char *name;

    Person(char *name) {
        this->name = name;
    }

    ~Person() {

    }

    void press_trigger(class AK47 *ak47) {
        cout << "扣动扳机\n";
        ak47->fire();
    }

    void press_trigger(class MP5 *mp5) {
        cout << "扣动扳机\n";
        mp5->fire();
    }

};


int main() {
    class Person laowang("老王");
    class AK47 ak47;
    class MP5 mp5;

    laowang.press_trigger(&ak47);
    laowang.press_trigger(&mp5);

    return 0;
}

在这里插入图片描述
第二个案例:
抽取基类

#include <iostream>

using namespace std;


class Gun {
public:
    void fire() {
        cout << "开火\n";
        this->push_bullet();
    }

    void push_bullet() {
        // 弹出子弹
        cout << "弹出子弹\n";
    }
};

class MP5 : public Gun {
public:

};


class AK47 : public Gun {
public:

};


class Person {
public:
    char *name;

    Person(char *name) {
        this->name = name;
    }

    ~Person() {

    }

    void press_trigger(class AK47 *ak47) {
        cout << "扣动扳机\n";
        ak47->fire();
    }

    void press_trigger(class MP5 *mp5) {
        cout << "扣动扳机\n";
        mp5->fire();
    }

};


int main() {
    class Person laowang("老王");
    class AK47 ak47;
    class MP5 mp5;

    laowang.press_trigger(&ak47);
    laowang.press_trigger(&mp5);

    return 0;
}



第三个案例:
重写父类函数

#include <iostream>

using namespace std;


class Gun {
public:
    void fire() {
        cout << "开火\n";
        this->push_bullet();
    }

    virtual void push_bullet() {
        // 弹出子弹
        cout << "弹出子弹\n";
    }
};

class MP5 : public Gun {
public:
    void push_bullet() {
        // 弹出子弹
        cout << "mp5弹出子弹\n";
    }
};


class AK47 : public Gun {
public:
    void push_bullet() {
        // 弹出子弹
        cout << "ak47弹出子弹\n";
    }
};


class Person {
public:
    char *name;

    Person(char *name) {
        this->name = name;
    }

    ~Person() {

    }

    void press_trigger(class AK47 *ak47) {
        cout << "扣动扳机\n";
        ak47->fire();
    }

    void press_trigger(class MP5 *mp5) {
        cout << "扣动扳机\n";
        mp5->fire();
    }

};


int main() {
    class Person laowang("老王");
    class AK47 ak47;
    class MP5 mp5;

    laowang.press_trigger(&ak47);
    laowang.press_trigger(&mp5);

    return 0;
}

在这里插入图片描述

第四个案例:
多态

#include <iostream>

using namespace std;


class Gun {
public:
    void fire() {
        cout << "开火\n";
        this->push_bullet();
    }

    virtual void push_bullet() {
        // 弹出子弹
        cout << "弹出子弹\n";
    }
};

class MP5 : public Gun {
public:
    void push_bullet() {
        // 弹出子弹
        cout << "mp5弹出子弹\n";
    }
};


class AK47 : public Gun {
public:
    void push_bullet() {
        // 弹出子弹
        cout << "ak47弹出子弹\n";
    }
};


class Person {
public:
    char *name;

    Person(char *name) {
        this->name = name;
    }

    ~Person() {

    }

//    void press_trigger(class AK47 *ak47) {
//        cout << "扣动扳机\n";
//        ak47->fire();
//    }
//
//    void press_trigger(class MP5 *mp5) {
//        cout << "扣动扳机\n";
//        mp5->fire();
//    }

    void press_trigger(class Gun *gun) {
        cout << "扣动扳机\n";
        gun->fire();
    }

};


int main() {
    class Person laowang("老王");
    class AK47 ak47;
    class MP5 mp5;

    laowang.press_trigger(&ak47);
    laowang.press_trigger(&mp5);

    return 0;
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

挥剑决浮云 -

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值