- 5
- 0
- 约 5页
- 2017-04-12 发布于四川
- 举报
C中构造函数中调用虚函数问题
C++中构造函数中调用虚函数的问题
在构造函数中调用虚成员函数,虽然这是个不很常用的技术,但研究一下可以加深对虚函数机制及对象构造过程的理解。这个问题也和一般直观上的认识有所差异。先看看下面的两个类定义。
struct C180
{
C180() {
foo();
this-foo();
}
virtual foo() {
cout C180.foo this: this vtadr: *(void**)this endl;
}
};
struct C190 : public C180
{
C190() {}
virtual foo() {
cout C190.foo this: this vtadr: *(void**)this endl;
}
};
父类中有一个虚函数,并且父类在它的构造函数中调用了这个虚函数,调用时它采用了两种方法一种是直接调用,一种是通过this指针调用。同时子类又重写了这个虚函数。
我们可以来预测一下如果构造一个C190的对象会发生什么情况。
我们知道,在构造一个对象时,过程是这样的:
1) 首先会按对象的大小得到一块内存(在heap上或在stack上),
2) 把指向这块内存的指针做为this指针来调用类的构造函数,对这块内存进行初始化。
3) 如果对象有父类就会先调用父类的构造函数(并依次递归),如果有多个父类(多重继承)会依次对父类的构造函数进行调用,并会适当的调整this指针的位置。在调用完所有的父类的构造函数后,再执行自己的代码。
照上面的分析构造C190时也会调用C180的构造函数,这时在C180构造函数中的第一个foo调用为静态绑定,会调用到C180::foo()函数。第二个foo调用是通过指针调用的,这时多态行为会发生,应该调用的是C190::foo()函数。
执行如下代码:
C190 obj;
obj.foo();
结果为:
C180.foo this: 0012F7A4 vtadr: 0045C404
C180.foo this: 0012F7A4 vtadr: 0045C404
C190.foo this: 0012F7A4 vtadr: 0045C400
和我们的分析大相径庭。第一行是在C180中运行foo()函数得到的,这里的foo()当然是调用C180中的foo()函数。第二行是调用C180中的this-foo()得到的,此时this指向的应该是C180的虚表地址,按照调用规则,应该是动态绑定,即,此时若派生类对该虚函数实现过,则应该调用派生类的虚函数,这里是一个例外,下面会详细讲到。 至此,C190的父类的构造函数运行完毕,转而运行C190的构造函数,但是这里C190的构造函数什么都没有。第三行是在main函数中调用obj.foo()得到的,这里直接进入C190运行就可以了。 这里必须注意一点,就是前两行和第三行的虚表是不同的,这是因为前两行的虚表是C180的虚表,而第三行的虚表是C190的虚表。 其实这正是奥秘所在。
为此我查了一下C++标准规范。在12.7.3条中有明确的规定。这是一种特例,在这种情况下,即在构造子类时调用父类的构造函数,而父类的构造函数中又调用了虚成员函数,这个虚成员函数即使被子类重写,也不允许发生多态的行为。即,这时必须要调用父类的虚函数,而不子类重写后的虚函数。
我想这样做的原因是因为在调用父类的构造函数时,对象中属于子类部分的成员变量是肯定还没有初始化的,因为子类构造函数中的代码还没有被执行。如果这时允许多态的行为,即通过父类的构造函数调用到了子类的虚函数,而这个虚函数要访问属于子类的数据成员时就有可能出错。
我们看看VC7.1生成的汇编代码就可以很容易的理解这个行为了。
这是C190的构造函数:
01 00426FE0 push ebp
02 00426FE1 mov ebp,esp
03 00426FE3 sub esp,0CCh
04 00426FE9 push ebx
05 00426FEA push esi
06 00426FEB push edi
07 00426FEC push ecx
08 00426FED lea edi,[ebp+FFFFFF34h]
09 00426FF3 mov ecx,33h
10 00426FF8 mov eax,0CCCCCCCCh
11 00426FFD rep stos dword ptr [edi]
12 00426FFF pop ecx
13 0042
您可能关注的文档
- 河北省冀州中学2009届高三保温卷(文综).doc
- 河北省冀州中学2010-2011届高一上学期期末考试(数学理A).doc
- 9年级英语unit5基础知识巩固练习题.doc
- 9年级英语unit3知识点总结.doc
- 9年级物理14.5家庭用电教案沪科版.doc
- 河北省冀州中学2010-2011届高一上学期期末考试(数学文B).doc
- 9年级英语上module7教案.doc
- 江西省高安中学10-11届高二上学期第一次月考(英语).doc
- 江西省高安中学10-11届高二下学期期中考试(化学)(创新班).doc
- 9年级美术下册课时教案.doc
- 人教版八年级上册历史精品教学课件 第六单元 中华民族的抗日战争 第17课 七七事变与全民族抗战 (6).ppt
- 人教版八年级上册历史精品教学课件 期末专题复习 专题二 中国人民近代化的探索 (2).ppt
- 人教版八年级上册历史精品教学课件 第二单元 近代化的早期探索与民族危机的加剧 第5课 甲午中日战争与列强瓜分中国狂潮 (2).ppt
- 人教版八年级上册历史精品教学课件 第七单元 人民解放战争 大概念引领下的大单元复习 (4).ppt
- 人教版八年级上册历史精品教学课件 第七单元 人民解放战争 第21课 人民解放战争的胜利 (2).ppt
- 人教版八年级上册历史精品教学课件 第三单元 资产阶级民主革命与中华民国的建立 第10课 中华民国的创建 (2).ppt
- 人教版八年级上册历史精品教学课件 第四单元 新民主主义革命的开始 第12课 新文化运动 (3).ppt
- 第四组塑料低温脆化温度测试详解演示文稿.ppt
- 第消费者行为演示文稿.ppt
- 第一部分用搜索方法求解问题演示文稿.ppt
原创力文档

文档评论(0)