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日

相关文章

  • MySQL的DML语言操作实例

    MySQL是一种关系型数据库管理系统,DML(Data Manipulation Language,数据操作语言)是MySQL用来操作数据的语言。下面介绍一下如何使用MySQL的DML语言操作数据。 创建表 使用CREATE TABLE语句可以创建一个新的数据表。下面是一个例子: CREATE TABLE students ( student_id INT …

    other 2023年6月25日
    00
  • winscp为何连接超时 winscp连接超时要学会去设置这三点

    WinSCP为何连接超时,WinSCP连接超时要学会去设置这三点 WinSCP是一个免费的SFTP、SCP、FTP和WebDAV客户端,它可以帮助用户在Windows操作系统上进行文件输。在使用WinSCP时,有时会遇到连接超时的问题。本攻略将详细介绍WinSCP连接超时的原因,并提三个设置来解决连接超时问题。 连接超时原因 WinSCP连接超时的原因可能有…

    other 2023年5月9日
    00
  • Java有序链表的合并实现方法

    一、有序链表的合并方法 在Java中,有序链表的合并方法可以通过递归实现,具体步骤如下: 如果两个有序链表中,其中一个为空,则返回另一个链表。 比较两个链表的头节点值,将较小的节点作为合并后链表的头节点。 将较小节点的下一个节点和另一个链表进行递归合并,将递归结果作为较小节点的下一个节点。 示例1:合并两个有序链表 链表1: 1 -> 3 -> …

    other 2023年6月27日
    00
  • linux学习日记十一 账号管理与ACL权限设置

    以下是详细的攻略: 账号管理 添加用户 可使用useradd命令添加用户,例如: sudo useradd -m -s /bin/bash username 其中,-m选项会在创建用户的同时自动为其创建家目录,-s选项则指定了shell类型为bash。 设置用户密码 使用passwd命令来设置用户的密码: sudo passwd username 删除用户 …

    other 2023年6月27日
    00
  • Android编程之退出整个应用程序的方法

    关于Android编程中的退出整个应用程序的方法,我能够提供如下的攻略: 使用系统提供的方法 在你的主Activity的onBackPressed()方法中,添加如下代码: java moveTaskToBack(true); android.os.Process.killProcess(android.os.Process.myPid()); System…

    other 2023年6月25日
    00
  • Win10一周年累积更新补丁KB3194496安装失败的解决方法 附独立更新包下载

    Win10一周年累积更新补丁KB3194496安装失败的解决方法攻略 问题描述 在安装Win10一周年累积更新补丁KB3194496时,可能会遇到安装失败的情况。本攻略将提供解决方法,并附上独立更新包的下载链接。 解决方法 以下是解决Win10一周年累积更新补丁KB3194496安装失败的方法: 重启计算机:有时候,安装失败是由于系统资源冲突或其他未知原因导…

    other 2023年8月3日
    00
  • 处理Shell脚本中带有空格的变量(bash脚本)

    当处理Shell脚本中带有空格的变量时,我们需要注意一些细节。下面是一个完整的攻略,包含了两个示例说明。 示例1:使用双引号引用变量 在Shell脚本中,我们可以使用双引号来引用带有空格的变量。这样可以确保变量的值被当作一个整体来处理。以下是一个示例: #!/bin/bash name=\"John Doe\" echo \"H…

    other 2023年8月16日
    00
  • vue多层嵌套路由实例分析

    Vue多层嵌套路由实例分析攻略 在Vue中,多层嵌套路由是一种常见的路由配置方式,它可以帮助我们构建复杂的应用程序,并实现页面之间的无缝切换。本攻略将详细介绍如何使用Vue的多层嵌套路由,并提供两个示例说明。 步骤一:创建Vue项目和路由配置 首先,我们需要创建一个Vue项目,并配置路由。可以使用Vue CLI来创建项目,然后在项目的根目录下找到router…

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