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++ 之 内存模型:虚函数篇的主要内容,如果未能解决你的问题,请参考以下文章

一文读懂C++虚函数的内存模型

C++对象内存模型2 (虚函数,虚指针,虚函数表)

c++ 之 内存模型:对象篇

c++虚函数内存模型(面试入坑之后的通透)

c++虚函数内存模型(面试入坑之后的通透)

c++对象内存模型内存布局