我的编程空间,编程开发者的网络收藏夹
学习永远不晚

C++深度探索虚函数指针示例

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

C++深度探索虚函数指针示例

代码描述:定义一个Person类为基类,ChinesePer 类与EnglishPer类都继承于此基类。

class Person
{
public:
	void speak() {
		cout << "说人话" << endl;
	}
private:
	int m_type = 1 ;
};
class ChinesePer :public Person {
public:
	void speak() {
		cout << "说中国话chinese..." << endl;
	}
};
class EnglishPer :public Person {
public:
	void speak() {
		cout << "说英国话english..." << endl;
	}
};

先看看此时各个类占用的内存信息:

int main() {
	int person_size = sizeof(Person);
	int Chineseper_size = sizeof(ChinesePer);
	int Englishper = sizeof(EnglishPer);
}

可以看到三个类的大小都为4个字节,占用的情况就是 类中的m_type变量。

将基类中的 speak() 函数加上virtual关键字 ,成为虚函数后再次查看内存字节大小:

可以看到多出了4个字节大小的空间(X86),三个类的大小都为 8。其实就是多出了一个指针的大小,4个字节 ,创建一个子类对象就可以明显看出来:

可以得出结论一:继承过来的成员变量 m_type(4个字节) + _vfptr(4个字节) = 8个字节。

继续探索虚函数表的原理, 创建以下子类对象并通过父类指针指向子类对象调用speak函数发生多态:

int main(){
	ChinesePer chs;
	ChinesePer chs2;
	EnglishPer eng;
    Person *ptr = &chs;		//父类指针指向子类对象
	Person *ptr1 = &chs2;
	Person *ptr2 = &eng;
	ptr->speak();
	ptr1->speak();
	ptr2->speak();
}

以上代码执行后会发生多态:

此时我们看看三个对象的内存分布:

用图片简要描述一下就是:

在这里可以先得到结论二: 同一个子类的所有对象共享一个虚函数表,指向虚函数表的指针_vptr是相同的。

在内存分布上查看一下 eng对象的虚函数指针地址情况:

可以看到该虚函数指针的地址上的值,存放的正是 该子类中的重写函数 speak()函数的地址。

如果把这个地址的值,修改为 Chineseper 类中的重写函数speak() 的地址值,会发生什么?

手动修改了eng对象中虚函数指针内的地址值,将改值本来是存放的是 EnglishPer 类中的speak() 函数的地址,现在更改为 ChinesePer 类中speak() 函数的地址。

单步走发生多态:

至此可以得出结论三:

当基类函数加了virtual 关键字后,虚函数的调用方法是间接调用:先查虚函数表的地址(也就是指向虚函数表的指针 _vptr),再查虚函数表中的虚函数指针。

不妨在基类继续添加两个虚函数

class Person
{
public:
	virtual void speak() {
		cout << "说人话" << endl;
	}
	virtual void eat() {
		cout << "吃饭" << endl;
	}
	virtual void sleep() {
		cout << "睡觉" << endl;
	}
private:
	int m_type =1 ;
};

子类只重写了speak函数,查看一下chs对象的虚函数指针地址存放的值:

的确存放的还是各个函数的地址,且是连续存放的,因此在进行查表调用虚函数的时候,也是每移动4个字节指向的就是一个函数的指针地址。

可以简要描述一下形式就很直观了:

总结:

1.增加了virtual 关键字的对象头部4个字节是一个指针,指向了虚函数表的地址(单继承情况下)。

2.同一个子类的所有对象共享一个虚函数表,指向虚函数表的指针_vptr是相同的。

3.当基类函数加了virtual 关键字后,虚函数的调用方法是间接调用:先查虚函数表的地址(也就是指向虚函数表的指针 _vptr),再查虚函数表中的虚函数指针。

到此这篇关于C++深度探索虚函数指针示例的文章就介绍到这了,更多相关C++虚函数内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

C++深度探索虚函数指针示例

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

C++深度探索虚函数指针示例

虚函数主要通过V-Table虚函数表来实现,该表主要包含一个类的虚函数的地址表,可解决继承、覆盖的问题,下面这篇文章主要给大家介绍了如何通过一篇文章带你掌握C++虚函数的来龙去脉,需要的朋友可以参考下
2022-12-19

C++深度探索虚函数覆盖示例

虚函数主要通过V-Table虚函数表来实现,该表主要包含一个类的虚函数的地址表,可解决继承、覆盖的问题,下面这篇文章主要给大家介绍了如何通过一篇文章带你掌握C++虚函数的来龙去脉,需要的朋友可以参考下
2022-12-19

C++ 函数指针与类型安全:深入探索二者的平衡

函数指针在 c++++ 中允许存储函数地址,但缺乏类型安全。为了增强安全性,c++11 引入了类型化回调,允许指定函数指针的签名。此外,类型不安全的函数指针转换可能导致未定义行为。通过使用类型安全回调和谨慎地进行函数指针转换,程序员可以在便
C++ 函数指针与类型安全:深入探索二者的平衡
2024-04-29

C++中返回指向函数的指针示例

int (*ff(int)) (int *,int);表示:ff(int)是一个函数,带有一个int型的形参,该函数返回int (*) (int *,int),它是一个指向函数的指针,所指向的函数返回int型并带有两个分别是Int*和int型的形参
2022-11-15

函数指针在现代 C++ 中的作用:探索新边疆

函数指针允许 c++++ 中的函数作为值存储和传递,提供灵活性并简化创建灵活可重用的代码。它们用于传递排序算法的比较器函数,自定义比较顺序,从而提高代码可读性和可维护性。函数指针在现代 C++ 中的作用:探索新边疆函数指针是一种 C++
函数指针在现代 C++ 中的作用:探索新边疆
2024-04-29

C++ 函数指针高级指南:探索高级用法和最佳实践

c++++ 函数指针的高级用法:函数指针数组:将多个函数指针存储在数组中,方便调用不同类型的函数。函数指针作为函数参数:将函数指针作为其他函数的参数,实现代码的动态性和可重用性。标准库函数指针:利用 std::function 和 std:
C++ 函数指针高级指南:探索高级用法和最佳实践
2024-04-29

C++ 函数返回值指南:类型和含义的深入探索

c++++ 函数返回值类型有基本类型、自定义类型、指针、引用和 void。返回值的含义可因上下文而异,包括运算结果、状态指示、输出参数和无返回值。实战案例演示了返回值在求和和获取用户名中的使用,使我们能够理解代码逻辑和数据流。C++ 函数返
C++ 函数返回值指南:类型和含义的深入探索
2024-05-03

C语言中返回值指针函数的示例分析

这篇文章主要为大家展示了“C语言中返回值指针函数的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“C语言中返回值指针函数的示例分析”这篇文章吧。 #includevo
2023-06-29

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录