代码随想录八股训练营第三十一天| C++

2024-09-03 05:36

本文主要是介绍代码随想录八股训练营第三十一天| C++,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

一、虚函数怎么实现的:

1.1.虚函数声明::

1.2.虚函数表(vtable):

1.3.函数指针::

1.4.动态绑定:

1.5.析构函数:

1.6.纯虚函数:

二、虚函数表是什么??

2.1. 虚函数表的工作原理::

2.2. 虚函数表的作用::

2.3.虚函数表的实现细节:

总结


前言

在面向对象编程中,多态性是一个核心概念,它允许我们以统一的方式处理不同类型的对象。虚函数是实现多态性的关键技术之一,它使得派生类能够重写基类中定义的行为。在C++等语言中,虚函数的实现依赖于虚函数表(vtable)和虚函数指针(vptr)等机制。本文将详细解释虚函数的实现原理和虚函数表的作用,以及它们如何共同工作以支持多态性和动态绑定。


一、虚函数怎么实现的:

虚函数是面向对象编程中的一个重要概念,它允许在派生类中重写基类中定义的函数。虚函数的实现通常依赖于编程语言的机制,但大多数支持面向对象的编程语言(如C++、Java、C#等)都有类似的实现方式。在C++中,虚函数的实现主要依赖于以下几个关键点:

1.1.虚函数声明

  • 在基类中,函数需要被声明为virtual,这告诉编译器这个函数可以被子类重写。
class Base {
public:virtual void func() {// 基类实现}
};

1.2.虚函数表(vtable)

  • 每个包含虚函数的类都有一个虚函数表(vtable),这是一个函数指针数组。每个对象都有一个指向其类vtable的指针(通常称为vptr)。

1.3.函数指针::

  • vtable中的每个条目都是一个函数指针,指向基类或派生类中虚函数的实现。

1.4.动态绑定

  • 当通过基类指针或引用调用虚函数时,程序运行时会使用对象的vptr来查找正确的vtable,然后调用相应的函数实现。这个过程称为动态绑定或晚期绑定。

1.5.析构函数

  • 如果基类的析构函数不是虚的,那么在删除派生类对象时,派生类的析构函数可能不会被调用,导致资源泄露。因此,通常建议将基类的析构函数声明为虚函数。
class Base {
public:virtual ~Base() {// 基类析构函数}
};

1.6.纯虚函数

  • 在基类中,可以声明一个纯虚函数(使用=0),这使得类成为抽象类,不能直接实例化,并且要求所有派生类都必须实现这个纯虚函数。
class Base {
public:virtual void func() = 0; // 纯虚函数
};

二、虚函数表是什么??

虚函数表(Virtual Table,简称vtable),是C++等支持多态的编程语言中用于实现虚函数机制的一种数据结构。它是一种实现动态绑定(Dynamic Binding)或晚期绑定(Late Binding)的技术,允许在运行时确定调用哪个函数。

2.1. 虚函数表的工作原理::

  • 存储函数指针:虚函数表是一个函数指针数组,每个指针指向一个虚函数的具体实现。这些指针指向基类和派生类中重写的虚函数。

  • 对象中的指针:每个包含虚函数的对象都有一个指向其类虚函数表的指针,这个指针通常称为vptr(Virtual Pointer)。vptr存储在对象的内存布局的最前面,以便快速访问。

  • 调用虚函数:当通过基类指针或引用调用虚函数时,编译器生成的代码会使用vptr来访问对应的虚函数表,然后通过虚函数表找到正确的函数指针,并调用相应的函数。

2.2. 虚函数表的作用::

  • 实现多态:虚函数表使得对象在运行时能够根据实际的派生类类型调用正确的函数实现,这是多态性的关键。
  • 动态绑定:它允许在运行时而不是编译时确定调用哪个函数,这提供了更大的灵活性。
//Base 类有一个虚函数 show()。
//Derived 类重写了 show() 函数。
//main 函数中创建了一个 Derived 类型的对象,但通过 Base 类型的指针 b 来访问。
//当调用 b->show() 时,程序会通过 b 指向的虚函数表找到 Derived 类的 show() 函数,并调用它。
class Base {
public:virtual void show() {cout << "Base show" << endl;}virtual ~Base() {}
};class Derived : public Base {
public:void show() override {cout << "Derived show" << endl;}
};int main() {Base* b = new Derived();b->show(); // 输出 "Derived show"delete b;return 0;
}

2.3.虚函数表的实现细节:

  • vptr:每个对象都有一个vptr,指向其类的虚函数表。
  • 构造函数和析构函数:在构造和析构对象时,vptr可能会被修改以指向当前类的虚函数表,以确保正确调用虚函数。
  • 纯虚函数:如果类中有纯虚函数,那么这个类就是一个抽象类,不能实例化,但可以用于虚函数表的创建。

总结

虚函数和虚函数表是C++中实现多态性的重要机制。虚函数允许派生类重写基类的行为,而虚函数表则存储了指向这些重写函数的指针,使得在运行时可以动态地调用正确的函数实现。这种机制不仅提供了灵活性,还允许程序在不知道对象确切类型的情况下,通过基类指针或引用调用正确的函数。此外,虚函数表还确保了即使在对象被删除时,也能正确地调用派生类的析构函数,避免资源泄露。通过理解虚函数和虚函数表的工作原理,我们可以更好地利用C++等面向对象编程语言的强大功能。

这篇关于代码随想录八股训练营第三十一天| C++的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1132171

相关文章

Linux下如何使用C++获取硬件信息

《Linux下如何使用C++获取硬件信息》这篇文章主要为大家详细介绍了如何使用C++实现获取CPU,主板,磁盘,BIOS信息等硬件信息,文中的示例代码讲解详细,感兴趣的小伙伴可以了解下... 目录方法获取CPU信息:读取"/proc/cpuinfo"文件获取磁盘信息:读取"/proc/diskstats"文

使用Java将DOCX文档解析为Markdown文档的代码实现

《使用Java将DOCX文档解析为Markdown文档的代码实现》在现代文档处理中,Markdown(MD)因其简洁的语法和良好的可读性,逐渐成为开发者、技术写作者和内容创作者的首选格式,然而,许多文... 目录引言1. 工具和库介绍2. 安装依赖库3. 使用Apache POI解析DOCX文档4. 将解析

C++使用printf语句实现进制转换的示例代码

《C++使用printf语句实现进制转换的示例代码》在C语言中,printf函数可以直接实现部分进制转换功能,通过格式说明符(formatspecifier)快速输出不同进制的数值,下面给大家分享C+... 目录一、printf 原生支持的进制转换1. 十进制、八进制、十六进制转换2. 显示进制前缀3. 指

C++中初始化二维数组的几种常见方法

《C++中初始化二维数组的几种常见方法》本文详细介绍了在C++中初始化二维数组的不同方式,包括静态初始化、循环、全部为零、部分初始化、std::array和std::vector,以及std::vec... 目录1. 静态初始化2. 使用循环初始化3. 全部初始化为零4. 部分初始化5. 使用 std::a

使用Python实现全能手机虚拟键盘的示例代码

《使用Python实现全能手机虚拟键盘的示例代码》在数字化办公时代,你是否遇到过这样的场景:会议室投影电脑突然键盘失灵、躺在沙发上想远程控制书房电脑、或者需要给长辈远程协助操作?今天我要分享的Pyth... 目录一、项目概述:不止于键盘的远程控制方案1.1 创新价值1.2 技术栈全景二、需求实现步骤一、需求

Java中Date、LocalDate、LocalDateTime、LocalTime、时间戳之间的相互转换代码

《Java中Date、LocalDate、LocalDateTime、LocalTime、时间戳之间的相互转换代码》:本文主要介绍Java中日期时间转换的多种方法,包括将Date转换为LocalD... 目录一、Date转LocalDateTime二、Date转LocalDate三、LocalDateTim

C++ vector的常见用法超详细讲解

《C++vector的常见用法超详细讲解》:本文主要介绍C++vector的常见用法,包括C++中vector容器的定义、初始化方法、访问元素、常用函数及其时间复杂度,通过代码介绍的非常详细,... 目录1、vector的定义2、vector常用初始化方法1、使编程用花括号直接赋值2、使用圆括号赋值3、ve

如何高效移除C++关联容器中的元素

《如何高效移除C++关联容器中的元素》关联容器和顺序容器有着很大不同,关联容器中的元素是按照关键字来保存和访问的,而顺序容器中的元素是按它们在容器中的位置来顺序保存和访问的,本文介绍了如何高效移除C+... 目录一、简介二、移除给定位置的元素三、移除与特定键值等价的元素四、移除满足特android定条件的元

jupyter代码块没有运行图标的解决方案

《jupyter代码块没有运行图标的解决方案》:本文主要介绍jupyter代码块没有运行图标的解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录jupyter代码块没有运行图标的解决1.找到Jupyter notebook的系统配置文件2.这时候一般会搜索到

Python获取C++中返回的char*字段的两种思路

《Python获取C++中返回的char*字段的两种思路》有时候需要获取C++函数中返回来的不定长的char*字符串,本文小编为大家找到了两种解决问题的思路,感兴趣的小伙伴可以跟随小编一起学习一下... 有时候需要获取C++函数中返回来的不定长的char*字符串,目前我找到两种解决问题的思路,具体实现如下: