C++中虚函数、虚表、虚指针实例讲解
来源:互联网 发布:无冬之夜 原生mac 编辑:程序博客网 时间:2024/05/22 06:38
虚表/虚指针
虚函数在c++中的实现机制就是用虚表和虚指针,但是具体是怎样的呢?从more effecive c++其中一篇文章里面可以知道:是每个类用了一个虚表,每个类的对象用了一个虚指针。具体的用法如下:
class A
{
public:
virtual void f();
virtual void g();
private:
int a
};
class B : public A
{
public:
void g();
private:
int b;
};
//A,B的实现省略
因为A有virtual void f(),和g(),所以编译器为A类准备了一个虚表vtableA,内容如下:
A::f 的地址
A::g 的地址
B因为继承了A,所以编译器也为B准备了一个虚表vtableB,内容如下:
A::f 的地址
B::g 的地址
注意:因为B::g是重写了的,所以B的虚表的g放的是B::g的入口地址,但是f是从上面的A继承下来的,所以f的地址是A::f的入口地址。
然后某处有语句 B bB;的时候,编译器分配空间时,除了A的int a,B的成员int b;以外,还分配了一个虚指针vptr,指向B的虚表vtableB,bB的布局如下:
vptr : 指向B的虚表vtableB
int a: 继承A的成员
A *pa = &bB;
pa的结构就是A的布局(就是说用pa只能访问的到bB对象的前两项,访问不到第三项int b)
那么pa->g()中,编译器知道的是,g是一个声明为virtual的成员函数,而且其入口地址放在表格(无论是vtalbeA表还是 vtalbeB表)的第2项,那么编译器编译这条语句的时候就如是转换:call *(pa->vptr)[1](C语言的数组索引从0开始哈~)。
这一项放的是B::g()的入口地址,则就实现了多态。(注意bB的vptr指向的是B的虚表vtableB)
另外要注意的是,如上的实现并不是唯一的,C++标准只要求用这种机制实现多态,至于虚指针vptr到底放在一个对象布局的哪里,标准没有要求,每个编译器自己决定。
class A
{
public:
virtual void f();
virtual void g();
private:
int a
};
class B : public A
{
public:
void g();
private:
int b;
};
//A,B的实现省略
A::f 的地址
B因为继承了A,所以编译器也为B准备了一个虚表vtableB,内容如下:
A::f 的地址
B::g 的地址
注意:因为B::g是重写了的,所以B的虚表的g放的是B::g的入口地址,但是f是从上面的A继承下来的,所以f的地址是A::f的入口地址。
然后某处有语句 B bB;的时候,编译器分配空间时,除了A的int a,B的成员int b;以外,还分配了一个虚指针vptr,指向B的虚表vtableB,bB的布局如下:
vptr : 指向B的虚表vtableB
int a: 继承A的成员
int b: B成员
A *pa = &bB;
pa的结构就是A的布局(就是说用pa只能访问的到bB对象的前两项,访问不到第三项int b)
那么pa->g()中,编译器知道的是,g是一个声明为virtual的成员函数,而且其入口地址放在表格(无论是vtalbeA表还是 vtalbeB表)的第2项,那么编译器编译这条语句的时候就如是转换:call *(pa->vptr)[1](C语言的数组索引从0开始哈~)。
这一项放的是B::g()的入口地址,则就实现了多态。(注意bB的vptr指向的是B的虚表vtableB)
另外要注意的是,如上的实现并不是唯一的,C++标准只要求用这种机制实现多态,至于虚指针vptr到底放在一个对象布局的哪里,标准没有要求,每个编译器自己决定。
FROM:http://blog.sina.com.cn/s/blog_6215fe350100fg9i.html
0 0
- C++中虚函数、虚表、虚指针实例讲解
- C实例---函数指针
- c++指针函数与函数指针实例讲解
- C语言 - 指针数组 多级指针 二维数组 实例讲解
- C语言中的函数指针学习讲解
- Linux中fork()函数实例讲解
- C++中虚函数的实例
- C程序中函数指针
- C/C++中函数指针
- C函数中指针参数
- C陷阱中--函数指针
- C/C++中函数指针
- 实例讲解C++编程中的虚函数与虚基类
- 函数指针讲解
- C语言指针讲解
- C语言指针讲解
- C语言中scanf()函数讲解
- [C++] 虚指针,虚表,虚函数地址打印
- CVPR读书笔记[4]:Gabor特征提取之Gabor核
- python+shell简易进程控制
- 比特币现在到了哪个阶段?
- 关于“using namespace std”
- 实例详解Django的 select_related 和 prefetch_related 函数对 QuerySet 查询的优化(三)
- C++中虚函数、虚表、虚指针实例讲解
- 几道简单题的巧妙解题思维-nyoj860
- Android中的Handler的post方法详解
- POJ 3670 Eating Together 二分解法O(nlgn)和O(n)算法
- ACM练级日志: POJ 1389
- (张龙讲学)java web学习---jsUnit、Ajax、JQuery
- hdu 4289 Control(网络流 最大流+拆点)(模板)
- ACM练级日志: POJ 1376
- 关于Android ViewPager与资源文件的矛盾关系