c++ 之 内存模型:虚函数篇
Posted sxgloverr1314
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c++ 之 内存模型:虚函数篇相关的知识,希望对你有一定的参考价值。
一、虚函数
1.虚函数表位置分析
类:有虚函数,这个类会产生一个虚函数表
类的对象:有一个指针(vptr)会指向类的虚函数表——虚函数表指针。(位置可能在类内存空间的开头,也可能在末尾,具体由编译器实现决定)
2.继承关系作用下虚函数的手工调用
拿到虚函数表的地址,通过定义函数指针并赋值的方式可以直接调用虚函数。子类的虚函数会覆盖父类的虚函数。
3.虚函数表分析
(1)一个类只有包含虚函数才会存在虚函数表,同属于一个类的对象共享虚函数表,但拥有各自的虚函数表指针(vptr)。当然所有的该类对象的vptr都指向同一个虚函数表。
(2)父类中有虚函数就等于子类中有虚函数。(父类中有虚函数表则子类中肯定有虚函数表) 因为子类会继承父类。
如果子类中将父类虚函数的virtual去掉,函数就不再是虚函数?
在父类中是虚函数,即使子类中该函数不写virtual,它依然是虚函数。
不管是父类还是子类,每一个类都只有属于自己的唯一虚函数表。子类中是否会存在多个虚函数表?
(3)如果子类中完全没有新的虚函数,则子类虚函数表的内容与父类虚函数表的内容相同。但两个虚函数表在内存中的位置是不同的。是两个虚函数表。虚函数表中的每一项包含一个虚函数的首地址,但如果子类的虚函数表某项和父类虚函数表某项代表同一个函数(这表示子类没有覆盖父类的虚函数)则该表项所指向的函数相同。
(4)超出虚函数表部分内容不可知。
(5)当子类对象为父类对象赋值时,子类中的属于父类的那一部分会被编译器自动区分(切割)出来并拷贝给父类对象;所以BaseClass base = derive;实际做了两件事:一、生成了一个base对象;二、用derive的部分值来对base对象进行了初始化。 (但此时编译器在处理base对象的虚函数表指针 值的时候,编译器会根据base的类型来自动决策为BaseClass 的虚函数表地址)
(4)OO(面向对象)和OB(基于对象)概念
C++是通过类的指针和引用来支持多态,这是一种程序设计风格,这就是我们常说的面向对象。object-oriented model
OB(object-base)也叫ADT抽象数据模型[abstract datatype model],不支持多态,执行速度更快。因为函数调用的解析不需要运行时决定(没有多态),比如Base *pbase = new Derive();Base &base2 = derive2;而是在编译期间完成,内存空间紧凑程度上更为紧凑,因为没有虚函数这些概念。
但OB(object-base)的设计灵活性上较差,C++既支持面向对象程序设计。也支持基于对象程序设计。
4.多重继承虚函数表分析
以上是关于c++ 之 内存模型:虚函数篇的主要内容,如果未能解决你的问题,请参考以下文章