C++ 虚函数及虚函数表详解

yizhihongxing

C++虚函数详解

虚函数概念

虚函数是一个特殊的类成员函数,它可以在派生类中进行重写,并且在运行时动态决定调用哪个版本。虚函数可以实现运行时的多态性,是面向对象编程的重要特性。

在C++中,我们通常使用关键字 virtual 来声明一个虚函数,如下所示:

class Shape {
public:
   virtual void draw() {
      std::cout << "Drawing Shape" << std::endl;
   }
};

class Line : public Shape {
public:
   void draw() override {
      std::cout << "Drawing Line" << std::endl;
   }
};

class Circle : public Shape {
public:
   void draw() override {
      std::cout << "Drawing Circle" << std::endl;
   }
};

int main() {
   Shape *shape;
   Line line;
   Circle circle;

   shape = &line;
   shape->draw(); // Drawing Line

   shape = &circle;
   shape->draw(); // Drawing Circle

   return 0;
}

在上面的代码中,我们定义了三个类 Shape、Line 和 Circle,其中 Shape 类定义了一个虚函数 draw(),它被重写了。Line 和 Circle 类在继承 Shape 类的同时,也重写了 Shape 类的虚函数 draw()。在 main() 函数中,我们创建了一个指针 shape,并将它分别指向 Line 类和 Circle 类的对象。当我们调用 shape->draw() 函数时,程序会自动判断当前 shape 指针指向的对象类型,并调用该对象中的 draw() 函数,实现了多态性的效果。

虚函数表

C++中的虚函数通过虚函数表来实现,每个包含虚函数的类都会有一个虚函数表,其中存储着该类所有虚函数的地址。在对象被创建时,每个对象都会有一个指向虚函数表的指针,这个指针通常被称为虚函数指针。当一个类被派生时,虚函数表也会被随之继承,并被其派生类所共享。

当程序调用一个虚函数时,实际调用的是虚函数表中存储的函数地址。因为虚函数表不同于一般的静态表,它需要在程序运行期间动态生成并填充,以便实现多态性。下面是一个简单的示例,说明虚函数表的作用。

#include<iostream>

class Shape {
public:
   virtual void draw() {
      std::cout << "Drawing Shape" << std::endl;
   }
};

void printVTable(void *obj_ptr) {
   size_t *vptr = *(size_t **)obj_ptr;
   std::cout << "Address of virtual table: " << vptr << std::endl;
   std::cout << "         First function: " << (void *)vptr[0] << std::endl;
   std::cout << "        Second function: " << (void *)vptr[1] << std::endl;
   std::cout << "         Third function: " << (void *)vptr[2] << std::endl;
}

class Line : public Shape {
public:
   void draw() override {
      std::cout << "Drawing Line" << std::endl;
   }
};

int main() {
   Shape *shape;
   Line line;
   shape = &line;
   shape->draw();

   printVTable(&line);

   return 0;
}

在上面的代码中,我们定义了一个 Shape 类,并在其中定义了一个虚函数 draw()。我们再定义一个派生类 Line,它重写了 Shape 类的虚函数 draw()。在 main() 函数中,我们创建了一个指针 shape,并将它指向 Line 类的一个对象。当我们调用 shape->draw() 函数时,程序会输出 "Drawing Line"。

接着,我们调用了函数 printVTable(&line),打印出了 Line 类的虚函数表。由输出结果可知,虚函数表中存储了三个函数地址,其中包括了 Line 类的 draw() 函数的地址。

总结

C++中的虚函数实现了面向对象编程中重要的特性——多态性。虚函数通过虚函数表来实现,在程序运行期间动态决定调用哪个函数。虚函数的实现在 C++ 程序设计中具有重要意义,它是实现多态性的重要手段之一。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++ 虚函数及虚函数表详解 - Python技术站

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

相关文章

  • 详解C++编程中运算符的使用

    详解C++编程中运算符的使用 C++是一种面向对象的编程语言,所以运算符在编程中非常重要。运算符可以用来执行各种算术和逻辑操作,使得程序变得更加灵活和高效。本文将详细讲解C++编程中运算符的使用,帮助读者了解各种运算符的使用和一些常见错误的避免方法。 算术运算符 C++中的算术运算符包括加、减、乘、除和取模运算符,它们可以应用于基本数据类型,如整数和浮点数。…

    other 2023年6月27日
    00
  • 电脑硬盘里的program files文件夹是什么意思

    电脑硬盘里的“program files”文件夹指的是安装在Windows操作系统上的应用程序和软件的主要目录,一般安装程序将软件安装到该目录下,同时该目录也是Windows操作系统中的受保护文件夹。 一般情况下,Windows操作系统在C盘下会默认创建一个名为“Program Files”的文件夹,主要用于存放已安装的软件和应用程序。这个文件夹的主要作用是…

    other 2023年6月27日
    00
  • 特殊用途的IP地址介绍

    特殊用途的IP地址介绍攻略 特殊用途的IP地址是为了满足特定需求而保留的一些IP地址范围。这些地址不用于常规的网络通信,而是用于特殊目的,如私有网络、广播、测试和回环等。在本攻略中,我们将详细介绍几种常见的特殊用途IP地址,并提供示例说明。 1. 私有IP地址 私有IP地址是为了在私有网络中使用而保留的地址范围。这些地址不在公共互联网上路由,因此可以在组织内…

    other 2023年7月30日
    00
  • win10频繁断网怎么办 win10系统间歇性断网的解决办法

    Win10频繁断网怎么办 原因分析 Win10系统频繁断网的原因可能有很多,以下是一些常见的原因: 网络线路问题,如网线松动或断开等; 网络驱动程序问题,如驱动程序未安装或驱动程序版本过老等; 病毒或木马感染,如系统被病毒或木马攻击,导致网络异常; 网络设置问题,如IP地址设置错误等; 网络管理问题,如路由器或交换机设置问题等; 网络接入速度问题,如网络连接…

    other 2023年6月26日
    00
  • win7系统电脑开机提示”ravmond.exe应用程序错误”的原因及三种解决方法

    标题 Win7系统电脑开机提示”ravmond.exe应用程序错误”的原因及三种解决方法 问题描述 在Windows 7系统中,开机时可能会遇到一个提示窗口,显示”ravmond.exe 应用程序错误”。这会导致电脑无法使用。那么这个错误的原因是什么?又有哪些方法可以解决呢?本文将详细阐述这个问题,以便用户能够有效地解决这一问题。 原因分析 ravmond.…

    other 2023年6月25日
    00
  • java 深入理解内存映射文件原理

    Java 深入理解内存映射文件原理攻略 什么是内存映射文件 内存映射文件是一种将磁盘上的文件映射到内存中的技术。通过内存映射文件,可以将文件的内容直接映射到内存中的字节数组,从而实现对文件的高效读写操作。在Java中,可以使用java.nio包中的MappedByteBuffer类来实现内存映射文件。 内存映射文件的原理 内存映射文件的原理是将文件的一部分或…

    other 2023年8月1日
    00
  • iOS/iPadOS 15 开发者预览版 Beta4(版本号19A5307g)正式更新

    iOS/iPadOS 15 开发者预览版 Beta4(版本号19A5307g)是苹果公司最新发布的最新开发者预览版,该版本正式更新了以下内容: 1.新增了一些桌面小部件和功能。2.增加了一些隐私保护措施。3.优化了一些系统功能。 如何升级到iOS/iPadOS 15 开发者预览版 Beta4(版本号19A5307g)? 安装苹果官方开发者证书。在苹果开发者网…

    other 2023年6月26日
    00
  • Golang实现单链表的示例代码

    下面是详细的攻略: 单链表简介 单链表是一种基础的数据结构,由若干个节点组成,每个节点包含数据和指向下一个节点的指针。最后一个节点指向空。单链表的优点是插入和删除操作非常方便,但查找效率较低。在Golang中,使用结构体和指针实现单链表比较方便。 实现单链表的代码 下面是实现单链表的示例代码,具体实现如下: package main import &quot…

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