• C++多态详解


    什么是多态?

    多态是指同一种行为对应不同的实现,即同名函数有不同的实现。多态是实现“一种接口(相同的函数名),多种方法(多种函数实现)”的技术。

    面向对象程序设计中,多态主要体现在:不同类的对象接收到同一个消息时会执行不同的动作(不同的实现)。

    多态的本质是:同名函数在不同类中有不同的实现。即不同功能的函数在不同类中具有相同的函数名。

    例如:

    “开”是一个行为,“开门”、“开车”、“开会”会有不同的结果。

    自然界中各种动物都有叫声,但不同动物的叫声却千差万别,如猫是喵喵叫,狗是汪汪 叫

    各种品牌、不同型号的手机都有开关机的功能。向手机发送开机指令都会打开手机, 但不同的手机开机时执行的行为却各不相同,初始化的硬件、启动的程序都会有差异。

    这些就是生活中多态的体现

    下面看一个例子

    1. #include
    2. using namespace std;
    3. class A
    4. {
    5. public:
    6. void display()
    7. {
    8. cout << "输出基类函数" << endl;
    9. }
    10. };
    11. class B :public A
    12. {
    13. public:
    14. void display()
    15. {
    16. cout << "输出派生类函数" << endl;
    17. }
    18. };
    19. int main()
    20. {
    21. A* p = new A();
    22. p->display();
    23. p = new B();
    24. p->display();
    25. }

    输出结果:

    1. 输出基类函数
    2. 输出基类函数

    从这个结果可以看出来,我们定义一个基类指针,先指向了基类,然后调用了基类的display函数,之后我们又将这个基类指针指向了派生类,调用派生类的display函数,但是我们看输出结果可以发现并没有调用派生类的display函数

    这是由于静态联编,静态联编后面会说。这里p的类型是A,所以调用的一直是A也就是基类的函数,我们想要调用派生类的函数该怎么办呢?这里就要用到虚函数

    虚函数

    为了让基类指针能够访问派生类的成员函数,C++增加了虚函数(在函数声明前增加 virtual 关键字)。

    下面把上面的代码用虚函数修改一下

    1. #include
    2. using namespace std;
    3. class A
    4. {
    5. public:
    6. int a = 10;
    7. public:
    8. virtual void display()
    9. {
    10. cout << "输出基类函数" << endl;
    11. }
    12. };
    13. class B :public A
    14. {
    15. public:
    16. void display()
    17. {
    18. cout << "输出派生类函数" << endl;
    19. a += 10;
    20. }
    21. };
    22. int main()
    23. {
    24. A* p = new A();
    25. p->display();
    26. p = new B();
    27. p->display();
    28. }

    输出结果

    1. 输出基类函数
    2. 输出派生类函数

    在基类的display函数前面加上virtual关键字,将成员函数声明为虚函数,这样就可以通过p指针调用派生类的函数了

    结论:

    有了虚函数,基类指针指向基类对象时就使用基类的成员(包括成员函数和成员变量), 指向派生类对象时就使用派生类的成员。换句话说,基类指针可以按基类的方式来做事, 也可以按派生类的方式来做事,有多种形态,或者说有多种表现方式,这种现象称为多 态。

    上面代码中:同样是p->display();语句,当p指向不同的对象时,它执行的操作是不同 的。同一条语句可以执行不同的操作,有不同表现方式,这就是多态。

    多态的应用

    下面看一个例子

    1. #include
    2. using namespace std;
    3. class Phone
    4. {
    5. public:
    6. virtual void display()
    7. {
    8. cout << "这里是电话类!" << endl;
    9. }
    10. };
    11. class Apple:public Phone
    12. {
    13. public:
    14. void display()
    15. {
    16. cout << "这里是苹果手机!" << endl;
    17. }
    18. };
    19. class Vivo :public Phone
    20. {
    21. void display()
    22. {
    23. cout << "这里是vivo手机!"<
    24. }
    25. };
    26. class Oppo :public Phone
    27. {
    28. void display()
    29. {
    30. cout << "这里是oppo手机!" << endl;
    31. }
    32. };
    33. class Mi :public Phone
    34. {
    35. void display()
    36. {
    37. cout << "这里是小米手机!" << endl;
    38. }
    39. };
    40. int main()
    41. {
    42. Phone* p = new Phone();
    43. p->display();
    44. p = new Apple();
    45. p->display();
    46. p = new Vivo();
    47. p->display();
    48. p = new Oppo();
    49. p->display();
    50. p = new Mi();
    51. p->display();
    52. }

    输出结果

    1. 这里是电话类!
    2. 这里是苹果手机!
    3. 这里是vivo手机!
    4. 这里是oppo手机!
    5. 这里是小米手机!

    这里我们利用虚函数访问了这几种派生类函数,这个例子中的派生类比较多,如果不使 用多态,那么就需要定义多个指针变量,很容易造成混乱;而有了多态,只需要一个指 针变量p就可以调用所有派生类的虚函数。

    结论:

    多态在小项目中鲜有用武之地,对于具有复杂继承关系的大中型程序,多态可以增加灵 活性,让代码更具有表现力。

    多态的目的:接口重用

    多态存在的目的是:

    为了实现接口重用,即无论给基类对象指针传递来的是基类还是派生类的对象,都能够通过同一个接口(函数)调用到适应各自对象的实现方法。即可以通过基类对象指针对所有派生类(包括直接派生和间接派生)的成员变量和成员函数进行“全方位”的访问,尤其是成员函数。

    多态的种类

    C++中多态按实现的时机分为两种:

    编译时多态:又称静态联编,程序在编译时就可确定(函数的)调用地址。通过重载机 制实现(包括函数重载和运算符重载)。

    函数重载:就是函数名相同但参数的类型和个数不同,功能相近的多个函数。不同函数 的调用地址在编译时即可确定。

    运算符重载:(其本质是函数重载)就是对已有的运算符赋予多重含义,一个运算符作 用于不同类型的数据就会导致不同的行为。

    运行时多态:又称为动态联编,必须在运行中才能确定函数的调用地址。通过继承和虚 函数实现,在基类与派生类中存在同名函数并且函数原型相同,这时可声明(基类中函 数)为虚函数(派生类中同名函数自动成为虚函数),在编译时无法确定调用哪个函数, 只有在程序运行时,才能确定调用基类还是派生类的同名函数。

    总结:

    不同类的对象接收到同一个消息时会产生不同的动作就是多态。

    不同类中对同名函数的不同实现,体现了多态的特征。

    继承结构和虚函数是实现多态的基础

    虚函数的唯一用处就是构成多态

    说明:

    前面介绍过,通过对象指针调用普通成员函数时,会根据指针的类型(哪个类的对象指针)来判断调用哪个类的成员函数,但它并不适用于虚函数,虚函数是根据对象指针的指向类型来调用的,对象指针指向哪个类的对象就调用哪个类的虚函数。

  • 相关阅读:
    语文课内外杂志语文课内外杂志社语文课内外编辑部2022年第3期目录
    在命令窗口便捷快速复制输出结果到剪贴板
    web课程设计网页规划与设计 :DW旅游主题网页设计——凤阳智慧旅游官方-地方旅游网站模板html源码HTML+CSS+JavaScript
    手把手教你从安装CentOS7.4镜像开始,搭建IoT视频监控系统
    oracle临时表
    【附源码】计算机毕业设计JAVA计算机在线学习管理系统-
    【pymysql的基本使用】
    js对象易混淆知识
    HMTL知识点系列(4)
    NFT: 开启加密艺术时代的无限可能
  • 原文地址:https://blog.csdn.net/qq_52905520/article/details/126860599