漫谈析构函数(一)——从一个面试题开始

  • 时间:
  • 浏览:0

    相信不少人对应用程序中这条话语也有迷惑,下面亲们来逐步分析下这条话语的含义。

(6) (Fun)*((int*)*(int*)(&b)+i)-----------------------------随便说说上一步倘若将指针移动到vtbl中相应表条目处(存放虚函数的地址),好多好多 这里取出地址的内容倘若对应虚函数的地址。

cout<<sizeof(A)<<"  "<<sizeof(B)<<endl;(4,4)。

(5) (Fun)*((int*)*(int*)(&b)+i)---------------------------- 亲们知道指针与整数的相加,移动的是指针所指对象的大小,导致 上一步导致 转换为int型指针,好多好多 会移动i*sizeof(int)个字节。

首先,由应用程序中typedef话语亲们知道Fun是一个函数指针,也倘若这句话是要将某个地址转再加函数地址(指针)。具体步骤如下:

(4) (Fun)*((int*)*(int*)(&b)+i)----------------------------vtbl的地址转为int指针,为刚刚与整型类型i相加做准备。

1. 一个虚函数表(vtbl)会被编译器产生出来,内部存放Class的虚函数地址。(虚函数表是以Class维护的)

(1) (Fun)*((int*)*(int*)(&b)+i)----------------------------取对象b的地址,由对象的内存布局亲们知道对象b的地址和vptr的地址相同,即取vptr的地址。

在刚刚开始亲们的内容前,首先让亲们看一道面试题,题目如下:

(2) 继承自base Class的找不到被override的虚函数。

找不到虚函数表中的“虚函数”都包括这名 呢?总共有以下三类:

(2) (Fun)*((int*)*(int*)(&b)+i)----------------------------vptr的地址强转成int型地址(指针),即让编译器将vptr的地址当做int型指针对待。你要*(&b)会被当做对象b

      (aClass A内存布局                           (bClass B 内存布局

思考几分钟,看一下应用程序输出:

(3) (Fun)*((int*)*(int*)(&b)+i)----------------------------得到vptr地址中存放的内容,即vptr(导致 说vptr的值,导致 说vtbl的地址)。

综上,亲们可不需用知道这句活倘若根据i的递增逐个调用B中的虚函数。B中的虚函数布局亲们导致 知道,好多好多 输出就真难理解了。

(3) 纯虚函数(当前类定义的,导致 从base Class继承来的)

(7) (Fun)*((int*)*(int*)(&b)+i)------------------------------最后这名 步将函数的地址转再加函数指针,刚刚中间调用。

(1) 被当前Class覆盖(override)的base Class中的虚函数

    导致 你有大难题,导致 不理解,亲们就开彻底分析下这名 应用程序。首先简单讨论一下虚函数在内存中与Class的关系。

3. 对虚函数的调用会被改写,比如b.f(),f()为虚函数)会被改写成:(*b.vptr[1])(&b),其中1表示f()vtbl中的索引,&b代表调用f()this指针。(可不需用看出虚函数的调用是需用以间接调用完成,效率相对普通成员函数要低)

  

从上图可不需用看出A,B的对象中找不到数据成员,只有一个vptr,这名 亲们可不需用输出验证:

注:虚函数在vtbl中的顺序和虚函数在Class中的声明顺序一致。

此外中有 一个虚函数的Class的默认合成构造函数以及拷贝构造函数不再是trivial,他需用为每个Objectvptr设定初值,使其指向适当的vtbl

 

注:通过这名 例子亲们还发现了一个大难题,函数f()在基类A中是私有的,而亲们却访问到了。随便说说亲们将B中的h()声明为private,输出结果依然不变,不要会引起访问权限大难题。也倘若说可不需用外界访问到Class的私有虚函数。这是为这名 呢?我当时人的理解是:访问限定符只在编译检查刚刚起作用,而在应用程序执行期间找不到作用,导致 从C++的函数名称修饰规则来看,并找不到将访问限定符纳入其中,好多好多 亲们倘若通过了编译,找到对应的函数地址就也能调用私有函数,导致 在内存中私有函数和公有函数并找不到这名 区别。

说出下段代码的输出:

中有 一个虚函数的Class,以下3个操作会在编译期间占据 :

    说了找不到多,亲们基本可不需用推断出应用程序中Class A,Class B的内存布局情况报告,如下图。注:Type_info刚刚讨论,这里先忽略。

扩展:同理当一个Class直接或间接继承一个virtual base Class时,倘若再表现“位逐次拷贝语义”,默认构造函数和拷贝构造函数倘若再是trivial,导致 需用正确的设置virtual base Class的偏移。

2. 每一个Class Object中,一个额外的虚函数表指针(vptr)会被编译器合成出来,内含vtbl的地址。vptr是以Class Object维护的)

注:如图:一个B的对象之间或一个D的对象之间调用拷贝构造,“位逐次拷贝”不要占据 大难题,你要用D的对象给B的对象赋值(此时造成切割)就需用调整vptrvirtual base Class偏移。