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

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日

相关文章

  • vue组件之时间组件

    以下是Vue组件之时间组件的完整攻略,包含两个示例说明: 步骤一:创建Vue组件 创建Vue组件。 在Vue项目中,创建一个名为TimePicker的Vue组件。 “`vue – {{ hour }} + – {{ minute }} + OK “` 在这个示例中,我们创建了一个名为TimePicker的Vue组件,该组件包含一个文本输入框和一个时间选择…

    other 2023年5月9日
    00
  • Win10开发必备:Visual Studio 2015部分官方ISO镜像下载地址

    Win10开发必备: Visual Studio 2015部分官方ISO镜像下载地址攻略 1. 简介 在Win10开发中,Visual Studio 2015是一个非常重要的开发工具。本攻略将详细介绍如何获取Visual Studio 2015的官方ISO镜像下载地址。 2. 步骤 2.1. 打开官方下载页面 首先,打开Visual Studio官方网站,进…

    other 2023年8月4日
    00
  • 详解JavaScript之ES5的继承

    详解JavaScript之ES5的继承 JavaScript是一种弱类型、基于原型的语言,它的继承机制跟其他面向对象语言不一样。在ES5中,可以使用以下几种方式实现继承: 1. 原型链继承 原型链继承是利用原型链中的关系进行继承,通过将父类的实例作为子类的原型,让子类实例可以访问父类实例上的属性和方法。但是它也有一些缺点,例如原型中的引用类型属性是共享的,子…

    other 2023年6月27日
    00
  • 详解ASP.NET提取多层嵌套json数据的方法

    详解ASP.NET提取多层嵌套JSON数据的方法 在ASP.NET中,提取多层嵌套JSON数据的方法可以通过以下步骤实现: 步骤1:获取JSON数据 首先,你需要获取包含多层嵌套JSON数据的字符串。这可以通过多种方式实现,例如从API调用、文件读取或用户输入等。 示例代码: string json = \"{\\\"name\\\&qu…

    other 2023年7月28日
    00
  • php实现parent调用父类的构造方法与被覆写的方法

    在PHP中,我们可以通过使用parent关键字来调用父类的构造方法与被覆写的方法。下面,我将详细讲解如何实现这个过程。 调用父类的构造方法 在子类中覆写了父类的构造方法后,如果我们需要调用父类的构造方法,就可以使用parent关键字来完成。 以下是一个示例代码: class Animal { protected $name; public function …

    other 2023年6月27日
    00
  • 浅谈PostgreSQL的客户端认证pg_hba.conf

    Pg_hba.conf文件是PostgreSQL数据库服务器配置中的一份非常关键的文件。它决定了客户端如何才能连接上PostgreSQL服务器,同时也控制了各种用户的访问权限。在本文中,我们将会深入浅出地介绍pg_hba.conf文件的相关知识。 什么是pg_hba.conf pg_hba.conf(Host-based Authentication)是一份…

    other 2023年6月27日
    00
  • bigdecimal乘法保留两位小数

    以下是“BigDecimal乘法保留两位小数”的完整攻略: BigDecimal乘法保留两位小数 在Java中,可以使用BigDecimal类来进行高精度计算。本攻略将介绍如何使用BigDecimal类进行乘法运算,并保留两位小数。 步骤1:创建BigDecimal对象 首先,您需要创建两个BigDecimal对象,表示要进行乘法运算的两个数。以下是创建Bi…

    other 2023年5月7日
    00
  • Win10 和 Win11可以共存吗? win10/11产品生命周期/服务更新介绍

    Win10 和 Win11可以共存吗? 根据微软官方的说法,Win10和Win11可以共存,也就是说,你的设备可以同时安装两个操作系统。不过,实际操作中需要注意以下几个问题: 1.先安装Win10还是Win11? 建议先安装Win10,再安装Win11。因为在Win11安装完成后,它会自动将系统启动条强制覆盖Win10,这样在重新开机时只能进入Win11,无…

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