关于effective C++的条款9~~~

飞翔的土豆 2010-02-03 10:24:56
梅耶讲:绝不在构造和析构函数中使用虚函数。即便使用了虚函数也不会带来预想的效果。
我直观理解为virtual函数在构造函数中相当于变成了普通的非虚函数。
我想问的是之所以出现这种“虚函数在构造函数中失效”的现象,是设计虚函数表自然而然产生的后果?还是说为了避免出现条款9中讲的那些不合理的情况,而额外针对构造函数的特别设计?
...全文
366 15 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
windsting 2010-02-05
  • 打赏
  • 举报
回复
推荐看《Thinking in C++》(第二版第一卷)的相关章节,
这是我读过的书,关于这个问题讨论最透彻的一本,
里面还告诉你怎么在构造和析构里面实现虚调用。
我忘了第几章,但你看到那两节的题目就知道是它了。
Kinloloy 2010-02-04
  • 打赏
  • 举报
回复
受益匪浅啊~~好
飞翔的土豆 2010-02-03
  • 打赏
  • 举报
回复
感谢LS高人!!受益匪浅!
xylicon 2010-02-03
  • 打赏
  • 举报
回复
是的,我是这个意思,更具体些说是,在基类的构造函数中vptr指向是基类的虚函数表。其他函数就按照对象本身vptr了。

有兴趣可以看看这个。很有趣的例子。正好说明这个问题。

http://www.codeguru.com/cpp/com-tech/atl/tutorials/article.php/c3545
飞翔的土豆 2010-02-03
  • 打赏
  • 举报
回复
请问10L,是否是说对象的基类部分构造完之前,vptr所指的是基类的虚函数表,等到构造子类部分是,子类构造函数修改了vptr使其指向了派生类的虚函数表??
xylicon 2010-02-03
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 r06041210 的回复:]
先感谢LS的解答,但自己仍无头绪,可能我问题描述的不清楚~~
在构造函数中调用虚函数的效果我已经验证,为什么应该出现这种效果我也理解了,我不明白的是这种结果是怎么出现的。。。是虚函数机制本来就可以保证这一效果?还是说虚函数在构造函数中调用会发生问题,于是额外有了一种机制,使虚函数在构造函数中变为非虚函数?
[/Quote]

这是基类的构造函数 做了虚表(vtable)的调整导致的。也就是说,构造函数中的this指针指向的虚表是自己的虚表。



飞翔的土豆 2010-02-03
  • 打赏
  • 举报
回复
7L的话让我有了点想法,不过条款9中上来一段梅耶就讲:“JAVA和C#程序员更要注意本条,因为这是C++与它们不相同的地方”。。。
飞翔的土豆 2010-02-03
  • 打赏
  • 举报
回复
先感谢LS的解答,但自己仍无头绪,可能我问题描述的不清楚~~
在构造函数中调用虚函数的效果我已经验证,为什么应该出现这种效果我也理解了,我不明白的是这种结果是怎么出现的。。。是虚函数机制本来就可以保证这一效果?还是说虚函数在构造函数中调用会发生问题,于是额外有了一种机制,使虚函数在构造函数中变为非虚函数?
ZangXT 2010-02-03
  • 打赏
  • 举报
回复
设计抉择吧。
java语言中,构造函数中调用方法就可以有多态现象产生。
cattycat 2010-02-03
  • 打赏
  • 举报
回复
对,还是构造函数顺序的问题。先构造基类,然后子类。如果基类的构造函数中调用子类的构造函数,此时子类还没初始化完会出错。
Dolphin_001 2010-02-03
  • 打赏
  • 举报
回复
你还是看2楼的解释吧,很清晰
xylicon 2010-02-03
  • 打赏
  • 举报
回复
构造子类的时候先构造基类,基类构造的时候,子类还没创建出来,所以在基类中使用虚拟函数来调用子类的相应的函数是无意义的。

同理,析构的时候,子类已经先析构了,也不能使用虚函数实现多态。
Dolphin_001 2010-02-03
  • 打赏
  • 举报
回复
构造函数和析构函数内,已经可以确定是在本类中执行了,用虚函数反而变复杂了,但并不实效。
stardust20 2010-02-03
  • 打赏
  • 举报
回复
当基类的构造函数调用一个virtual函数时,不调用覆盖函数
例如,假如Derived类覆盖一个继承的virtual函数f(),而且Base::Base()调用f()。由于在Base::Base()的执行期间对象是一个Base,所以应调用Base::f()。假如C++允许Base::Base()调用Derived::f(),那么Derived::f()就可能调用还没构造的成员对象上的成员函数。
同样,当基类的析构函数调用一个虚拟函数时,也不调用覆盖函数
所以在构造或者析构函数中调用虚拟函数时,最好指出它所属的类如Base::Base();
a_rockboy 2010-02-03
  • 打赏
  • 举报
回复
和基类与子类的初始化顺序有关吧。基类初始化时,子类的数据成员尚未初始化,就算能调用子类的虚函数,也会产生无法预测的错误。

65,186

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧