虚指针存在证明及虚函数表
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 其次。由于他会在虚函数表中多占领一块内存空间,浪费空间。