c++语言中虚函数实现多态的原理详解

当一个类中有虚函数时,编译器会在这个类的对象中生成一个虚函数表,表中存储着虚函数的地址。当这个类产生派生类并且派生类中也定义了虚函数时,这个派生类会继承父类的虚函数表,然后在自己的虚函数表中添加自己的虚函数或者重载父类中的虚函数,这个过程叫做动态联编。

使用虚函数可以实现多态,多态可以让不同的子类对象调用相同的虚函数,实现统一的行为表现,提高了代码的复用性和维护性。

下面分别用两条示例说明虚函数实现多态的原理。

示例一:

#include <iostream>
using namespace std;

class Animal{
public:
    virtual void speak(){
        cout << "动物在说话" << endl;
    }
};

class Cat : public Animal{
public:
    void speak(){
        cout << "小猫在说话" << endl;
    }
};

class Dog : public Animal{
public:
    void speak(){
        cout << "小狗在说话" << endl;
    }
};

int main()
{
    Animal *animal1;
    Cat cat1;
    Dog dog1;

    animal1 = &cat1;
    animal1->speak();

    animal1 = &dog1;
    animal1->speak();

    return 0;
}

示例说明:

  • 定义了一个动物类,其中speak虚函数在子类中被重载。
  • 定义了两个子类,分别是猫和狗,这两个子类都重载了speak函数。
  • 在主函数中创建了一个动物指针类型的指针变量,animal1。
  • 首先将这个指针指向猫对象cat1,调用animal1->speak()函数,此时输出“小猫在说话”。
  • 然后将这个指针指向狗对象dog1,再次调用animal1->speak()函数,此时输出“小狗在说话”。

原因分析:

  • 通过animal1指针指向不同的对象,虽然调用的函数名称相同,但却实现了不同的行为,实现了多态。
  • 在当下的编译器实现中,调用函数时,首先查找使用virtual关键字定义的函数,如果没有找到虚函数,则使用重载过的函数,如果还没有找到,则找到与函数名称相同的函数。

示例二:

#include <iostream>
using namespace std;

class Parent{
public:
    int num;
    virtual void func(){
        cout << "This is Parent's func" << endl;
    }
};

class Child : public Parent{
public:
    int num;
    void func(){
        cout << "This is Child's func" << endl;
    }
};

int main()
{
    Parent *pParent = new Child();
    pParent->num = 1; // 父类中num的值
    static_cast<Child *>(pParent)->num = 2; // 子类中num的值
    cout << "num in Parent: " << pParent->num << endl;
    cout << "num in Child: " << static_cast<Child *>(pParent)->num << endl;

    pParent->func(); // 多态,调用子类中重载的虚函数

    delete pParent;
    return 0;
}

示例说明:

  • 定义了一个父类,其中定义了一个变量num和一个虚函数func。
  • 定义了一个子类,也包含了一个变量num和一个重载了虚函数func的同名函数。
  • 在主函数中通过一个Parent指针指向一个Child对象,这个过程中实现了向上转型。同时,在对Parent指针类型变量进行操作时,会使用父类中的变量和函数。
  • 通过static_cast强制类型转换获取Child对象中的num值进行操作。
  • 调用pParent指针类型变量的func函数,这里实现了多态。

原因分析:

  • pParent通过指向子类对象实现了向上转型,实现了父类指针指向子类对象的行为表现。
  • 使用Cast操作符将parent类型的指针转化为指向子类对象的child类型的指针,实现了对子类对象中num变量的操作。
  • 多态中使用的是编译器查找虚函数的方式,调用的是子类中重载的虚函数。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:c++语言中虚函数实现多态的原理详解 - Python技术站

(0)
上一篇 2023年6月26日
下一篇 2023年6月26日

相关文章

  • Android跳转三方应用实例代码

    Android跳转三方应用实例代码 在Android开发中,我们经常需要跳转到其他应用程序,例如打开浏览器、拨打电话、发送短信等。下面是两个示例说明如何实现跳转到三方应用的代码。 示例1:打开浏览器 String url = \"https://www.example.com\"; Intent intent = new Intent(I…

    other 2023年10月13日
    00
  • docker mysql启动时执行初始化sql

    想要在docker中启动MySQL时自动执行初始化sql文件,可以通过以下步骤来实现: 1. 创建一个目录用于存放初始化文件 我们首先需要创建一个目录,用于存放我们的初始化sql脚本文件。 $ mkdir db_init_sql 2. 编写初始化sql脚本文件 在创建的目录下,我们需要创建一个或多个初始化sql脚本文件。这些sql文件包含了我们要在MySQL…

    other 2023年6月20日
    00
  • iphone设备总是提示存储空间不足怎么办 iphone存储空间清理方法教程

    iPhone设备提示存储空间不足怎么办? 背景 随着 iPhone 发展,手机内置存储空间不断增加,但是由于用户需求的不断增长,存储空间问题仍然是很普遍的。很多用户在使用 iPhone 常常会遇到 iPhone 设备内存不足的情况,这对用户的正常使用造成了很大的困扰。下面给出 iPhone 存储空间的清理方法。 iPhone存储空间清理方法教程 1. 清理照…

    other 2023年6月28日
    00
  • mariadb卸载

    Mariadb卸载攻略 Mariadb是一个流行的开源关系型数据库管理系统,但有时您可能需要卸载它。以下是在Linux系统上卸载Mariadb的步骤: 1. 停止Mariadb 在卸载Mariadb之前,您需要停止Mariadb服务。您可以使用以下命令停止Mariadb服务: sudo systemctl stop mariadb“` ### 2. 卸载M…

    other 2023年5月6日
    00
  • 如何在苹果Mac电脑上更改文件的扩展名?

    当你在苹果Mac电脑上需要更改文件的扩展名时,可以按照以下步骤进行操作: 首先,找到你想要更改扩展名的文件。你可以通过Finder或者桌面上的图标来找到它。 选中该文件,然后按下\”回车\”键或者右键点击该文件并选择\”重命名\”。 文件名会被选中并进入编辑模式。现在,你可以更改文件名和扩展名。 要更改扩展名,你需要在文件名后面添加一个句点(.)和新的扩展名…

    other 2023年8月5日
    00
  • c#原子操作理解

    c#原子操作理解 在多线程编程中,由于多个线程同时访问同一个变量,会引发资源竞争问题,导致数据出现异常结果。为了解决这个问题,我们可以使用原子操作(Atomic Operations)来保证操作的原子性,从而避免多线程下的竞争条件。 在C#中,提供了很多的原子性操作类,如Interlocked、Volatile等。这些类给我们提供了一种比较简单的方法来保证线…

    其他 2023年3月28日
    00
  • 深入探讨:linux中遍历文件夹下的所有文件

    我们一步步来解析如何在Linux中遍历文件夹下的所有文件。 Step 1: 使用 find 命令 在Linux中,可以使用 find 命令来遍历文件夹下的所有文件。下面是 find 命令的基本语法: find <path> <options> 其中,<path> 表示要遍历的路径,<options> 表示额外的…

    other 2023年6月26日
    00
  • Vue3+TypeScript实现递归菜单组件的完整实例

    下面我来详细讲解“Vue3+TypeScript实现递归菜单组件的完整实例”的完整攻略。实现递归菜单组件可以帮助我们在Vue3的开发过程中更快速更高效地实现菜单递归渲染。具体步骤如下: 1. 创建递归菜单组件 首先,我们需要创建递归菜单组件。组件名称为MenuList.vue。在代码块中,我们需要定义该组件的Props类型,包括菜单列表数组以及嵌套层数。在组…

    other 2023年6月27日
    00
合作推广
合作推广
分享本页
返回顶部