虚指针存在证明及虚函数表

简介:
C++多态的实现原理是依赖虚指针来辨别详细使用家族类中的哪一个函数。

下面就来证明虚指针的存在。 我们知道,指针的大小在普通情况下是4个字节,所以我们建立一个虚函数,再来计算该类的大小,便能够验证虚函数的存在。

代码例如以下:

#include <iostream>
using namespace std;

class A
{
public:
                 void print ()
                {

                }
private:
                 int a ;
};

class B
{
public:
                 virtual void print()
                {

                }
private:
                 int a ;
};


void main ()
{
                 cout << "sizeof(A)" << sizeof( A) << endl ;
                 cout << "sizeof(B)" << sizeof( B) << endl ;
                 system("pause" );
}

执行结果: 
这里写图片描写叙述 
A类与B类的,唯一区别就是在B类中 print()变成了一个虚函数,实验结果看到B类却比A类多出了4个字节。那说明在B类中。编译器隐藏的加入了一个虚指针的成员变量。

接下来在验证。一个类中。有多个虚函数。会不会分配多个虚指针:

#include <iostream>
using namespace std;

class B
{
public:
                 virtual void print()
                {

                }
                 virtual void print2()
                {

                }
private:
                 int a ;
};

void main ()
{
                 cout << "sizeof(B)" << sizeof( B) << endl ;
                 system("pause" );
}

执行结果: 
这里写图片描写叙述 
这就说明了,一个类中无论有几个虚函数,都仅仅会生成一个虚指针变量。 
这个虚指针变量实质上是指向一个虚函数表。我们先来看下什么是虚函数表。

虚函数表定义: 
类的虚函数表是一块连续的内存,每一个内存单元中记录一个JMP指令的地址。

注意的是,编译器会为每一个有虚函数的类创建一个虚函数表。该虚函数表将被该类的全部对象共享。

类的每一个虚成员占领虚函数表中的一行。假设类中有N个虚函数。那么其虚函数表将有N*4字节的大小。也就是说虚函数表是一块连续的内存。每一个虚成员。都会占领一块内存空间。

在平时设计代码是假设明白不须要使用虚函数,那就不要随便使用: 
1 主要原因是,虚指针调用虚函数是在程序执行时进行的,所以须要通过寻址操作才干找到真正应该调用的函数,而普通成员函数是在编译时就确定了调用的函数。不须要寻址操作。因此在效率上。虚函数的效率要低非常多。 
2 其次。由于他会在虚函数表中多占领一块内存空间,浪费空间。





本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/5312823.html,如需转载请自行联系原作者

相关文章
|
3月前
|
存储 程序员 C++
程序员必知:【C++】虚函数表vtable理解
程序员必知:【C++】虚函数表vtable理解
18 0
|
4月前
|
C++
第十二章:C++中的this指针详解
第十二章:C++中的this指针详解
40 0
|
存储 算法 编译器
【C++技能树】类的六个成员函数Ⅰ --构造、析构、拷贝构造函数
在开始本章内容之前,先浅浅的了解一下this指针的概念.这对理解后面的内容有着很大的帮助.
79 0
|
算法
绪论以及递归式上界函数的证明
绪论以及递归式上界函数的证明
|
存储 编译器 C++
【C++要笑着学】虚函数表(VBTL) | 观察虚表指针 | 运行时决议与编译时决议 | 动态绑定与静态绑定 | 静态多态与动态多态 | 单继承与多继承关系的虚表(二)
虚表是编译器的实现,而非C++的语言标准。上一章我们学习了多态的概念,本章我们深入探讨一下多态的原理。文章开头先说虚表指针,观察编译器的查表行为。首次观察我们先从监视窗口观察美化后的虚表 _vfptr,再透过内存窗口观察真实的 _vfptr。我们还会探讨为什么对象也能切片却不能实现多态的问题。对于虚表到底存在哪?我们会带着大家通过一些打印虚表的方式进行比对!铺垫完虚表的知识后,会讲解运行时决议与编译时决议,穿插动静态的知识点。文章的最后我们会探讨单继承与多继承的虚表,多继承中的虚表神奇的切片指针偏移问题,这块难度较大,后续我们会考虑专门讲解一下,顺带着把钻石虚拟继承给讲了
345 1
【C++要笑着学】虚函数表(VBTL) | 观察虚表指针 | 运行时决议与编译时决议 | 动态绑定与静态绑定 | 静态多态与动态多态 | 单继承与多继承关系的虚表(二)
|
Java 程序员 API
面向对象思想之使类和成员的可访问性最小化
讨论面向对象思想中的类和成员的可访问性,以及最小化的必要性
84 0
|
存储 编译器 C++
【C++要笑着学】虚函数表(VBTL) | 观察虚表指针 | 运行时决议与编译时决议 | 动态绑定与静态绑定 | 静态多态与动态多态 | 单继承与多继承关系的虚表(一)
虚表是编译器的实现,而非C++的语言标准。上一章我们学习了多态的概念,本章我们深入探讨一下多态的原理。文章开头先说虚表指针,观察编译器的查表行为。首次观察我们先从监视窗口观察美化后的虚表 _vfptr,再透过内存窗口观察真实的 _vfptr。我们还会探讨为什么对象也能切片却不能实现多态的问题。对于虚表到底存在哪?我们会带着大家通过一些打印虚表的方式进行比对!铺垫完虚表的知识后,会讲解运行时决议与编译时决议,穿插动静态的知识点。文章的最后我们会探讨单继承与多继承的虚表,多继承中的虚表神奇的切片指针偏移问题,这块难度较大,后续我们会考虑专门讲解一下,顺带着把钻石虚拟继承给讲了
556 0
【C++要笑着学】虚函数表(VBTL) | 观察虚表指针 | 运行时决议与编译时决议 | 动态绑定与静态绑定 | 静态多态与动态多态 | 单继承与多继承关系的虚表(一)
|
编译器 C++
虚析构函数、虚函数结合考题变种
虚析构函数、虚函数结合考题变种
100 0
虚析构函数、虚函数结合考题变种
|
Java 程序员 C++
C++雾中风景4:多态引出的困惑,对象的拷贝?
C++作为一门面向对象的语言,自然具备了面向对象的三大特征:封装,继承,多态。在学习多态性质的过程中,发现了C++与其他语言很大的区别(坑?)。在C++中的=操作符的使用与C++呈现的内存模型似乎并不是我所习惯的模式,在拷贝与引用两个不同操作之间摇摆,还是很容易写出存在问题的代码,所以也就引出了今天这篇文章,我们来聊聊=操作符背后的故事。
1088 0