一篇文章带你掌握C++虚函数的来龙去脉

yizhihongxing

一篇文章带你掌握C++虚函数的来龙去脉

背景

C++中的虚函数是一个较为复杂的概念,但又是一个非常重要的特性。在C++中,新手程序员非常容易出现“虚函数”与“普通函数”的混淆,不理解其来龙去脉,导致代码出现各种问题。本篇文章将系统地介绍C++虚函数的基础知识,包括虚函数的用途,实现原理,虚函数表,以及多重继承等问题,帮助读者全面掌握C++虚函数的来龙去脉。

虚函数的用途

在C++中的虚函数主要有两个作用:

  1. 实现运行时多态(Runtime Polymorphism):通过使用虚函数,实现基类和派生类之间的运行时多态。

  2. 实现动态绑定(Dynamic Binding):使用虚函数,可以解决使用基类指针或引用时无法正确调用派生类函数的问题。

虚函数实现原理

在C++中,虚函数的实现依赖于虚函数表(Virtual Table)的概念。虚函数表是一个包含一系列指向虚函数的指针数组。这个数组存放在对象或者类的只读数据段中,每个类拥有一个对应的虚函数表,存放着该类所定义的虚函数指针。当类的某个对象被实例化时,对象会向父类索要虚函数表指针,并把它的虚函数表指针指向该表。

当调用一个对象的虚函数时,实际上是通过对象指针的虚函数表指针找到该表,根据虚函数在表中的偏移量,得到该函数的地址进行调用。

虚函数表

虚函数表是由编译器自动生成,存储在只读数据段中。虚函数表存储着一堆指向虚函数的指针,每一个在类中定义的虚函数,都被分配一个指针在虚函数表中。派生类的虚函数表中都有一个和基类虚函数表相同的前缀,以保证虚函数在继承中的正确性。

多重继承中的虚函数问题

当类继承至少两个基类,并且这些基类都定义了同名的虚函数时,派生类将会有多个虚函数表,每个虚函数表对应基类的虚函数表。派生类的虚函数表是由基类的虚函数表构成的,这个基类的虚函数表是第一次在继承体系中出现该函数的虚函数表。这就意味着,如果一个派生类对象通过一个基类对象指针访问它的同名虚函数,那么该基类虚函数表中的函数将被执行,不是派生类虚函数表中的函数。

示例说明

下面的代码示例演示了虚函数的使用,以及基类指针调用派生类的虚函数:

#include<iostream>
using namespace std;

class Base 
{
public:
    virtual void func() 
    {
        cout<<"This is Base::func()"<<endl;
    }
};

class Derived:public Base 
{
public:
    void func() 
    {
        cout<<"This is Derived::func()"<<endl;
    }
};

int main() 
{
    Base *b1=new Base();
    Base *b2=new Derived();
    b1->func();
    b2->func();
    return 0;
}

执行输出结果:

This is Base::func()
This is Derived::func()

在上面的代码中,我们定义了一个基类Base和一个派生类Derived。在Base类中,我们定义了一个虚函数func,之后在Derived类中重写了基类函数func。在主函数中,我们通过基类指针调用了基类和派生类的函数。结果表明,通过基类指针调用派生类的虚函数后,会动态绑定到派生类的虚函数,实现了多态的功能。

下面的代码示例演示了多重继承中的虚函数问题:

#include<iostream>
using namespace std;

class Base1 
{
public:
    virtual void func() 
    {
        cout<<"This is Base1::func()"<<endl;
    }
};

class Base2 
{
public:
    virtual void func() 
    {
        cout<<"This is Base2::func()"<<endl;
    }
};

class Derived:public Base1,public Base2 
{
public:
    void func() 
    {
        cout<<"This is Derived::func()"<<endl;
    }
};

int main() 
{
    Base1 *b1=new Derived();
    Base2 *b2=new Derived();
    b1->func();
    b2->func();
    return 0;
}

执行输出结果:

This is Derived::func()
This is Derived::func()

在上面的代码中,我们定义了两个基类Base1Base2,在这两个基类中定义了相同的函数func。然后我们定义了一个派生类Derived,并继承了这两个基类。在Derived类中我们重写了基类函数func

在主函数中,我们用Base1Base2类型的指针分别指向派生类对象。实验结果表明,两次调用都是执行的派生类的虚函数。这是因为多重继承使得Derived类存在两个虚函数表,而使用基类指针调用虚函数时,靠前的基类虚函数将被执行。因此,在上面的代码中,两个指针都指向了派生类的虚函数表中的函数,所以两次输出结果一致。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:一篇文章带你掌握C++虚函数的来龙去脉 - Python技术站

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

相关文章

  • java递归设置层级菜单的实现

    Java递归设置层级菜单的实现,可以通过以下几个步骤来完成: 设计数据模型 首先需要设计数据模型,以便存储菜单的信息。这里我们可以使用一个Menu类来表示菜单,它包含以下几个属性: id:菜单的唯一标识符。 name:菜单名称。 parentId:菜单的父节点标识符,如果为0表示该菜单是顶级菜单。 children:菜单的子节点列表,如果没有子节点则为nul…

    other 2023年6月27日
    00
  • Android应用程序“R文件”消失

    当Android应用程序的“R文件”消失时,通常会出现一系列编译错误,例如“无法解析符号R”等。这种情况可能是由于以下原因之一: XML文件错误:如果XML文件(例如布局文件)中存在错误,可能会导致R文件消失。这些错误可能是拼写错误、标签未关闭或XML文件结构不正确等。 资源文件重复:如果存在重复的资源文件(例如两个具有相同名称的图像文件),则可能会导致R文…

    other 2023年6月25日
    00
  • asp.net简述MVC开发模式

    ASP.NET简述MVC开发模式 MVC是Model-View-Controller的缩写,是一种软件设计模式。这种模式将一个应用程序分成三个核心部分:模型(Model)、视图(View)以及控制器(Controller)。MVC模式在ASP.NET中的应用越来越广泛,下面我们来详细了解一下。 MVC模型 模型(Model)表示应用程序的核心(比如数据库记录…

    其他 2023年3月28日
    00
  • windows命令行切换目录

    windows命令行切换目录 在Windows操作系统中,如果需要在命令行中切换目录,可以使用cd命令。cd是英文change directory的缩写,意为改变当前工作目录。 语法 cd [目录路径] 其中,目录路径可以是相对路径或绝对路径。 相对路径:相对于当前工作目录的路径,如cd Desktop表示进入当前用户的桌面目录。 绝对路径:完整的目录路径,…

    其他 2023年3月29日
    00
  • 怎么修改手机ip地址?手机ip地址更改方法介绍

    怎么修改手机IP地址?手机IP地址更改方法介绍 1. 使用静态IP地址 打开手机的设置菜单。 在设置菜单中,找到并点击“网络设置”或类似选项。 在网络设置中,找到并点击“Wi-Fi”或类似选项。 找到当前连接的Wi-Fi网络,并长按该网络名称,然后选择“修改网络”或类似选项。 在修改网络设置中,找到并点击“高级选项”或类似选项。 在高级选项中,找到并点击“I…

    other 2023年7月30日
    00
  • 怎样给U盘加密 给U盘隐私上把锁

    给U盘加密有多种方法,本文将介绍两种常用的方式:使用加密软件和使用Windows自带的加密功能。 使用加密软件 在网上下载并安装一个可信赖的加密软件,例如TrueCrypt或VeraCrypt 。(本文以TrueCrypt为例) 打开TrueCrypt,点击“Volume creation”,选择“Creat Volume in a file” 选择加密文件…

    other 2023年6月27日
    00
  • Java使用递归回溯完美解决八皇后的问题

    Java使用递归回溯完美解决八皇后问题 什么是八皇后问题 八皇后是一个以棋盘为底盘,放置八个皇后的问题,皇后拥有垂直、水平和对角线的移动能力,要求任意两个皇后都不能在同一行、同一列或同一对角线上。 解题思路 因为任意两个皇后不能在同一行、同一列或同一对角线上,因此我们可以通过递归回溯的思路,按行对皇后进行放置,逐步约束各个皇后的位置,以达到放置成功且不冲突的…

    other 2023年6月27日
    00
  • 网站制作不可不知的URL知识

    网站制作不可不知的URL知识攻略 在网站制作过程中,URL(统一资源定位符)是非常重要的一部分。它不仅是用户访问网站的入口,还对搜索引擎优化(SEO)和用户体验起着重要作用。下面是一份详细的URL知识攻略,帮助你了解网站制作中不可不知的URL知识。 1. URL的基本结构 URL由多个部分组成,包括协议、域名、路径和查询参数等。以下是URL的基本结构: 协议…

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