`
kanwoerzi
  • 浏览: 1639701 次
文章分类
社区版块
存档分类
最新评论

Effective c++学习笔记——条款09:绝不在构造和析构过程中调用virtual函数

 
阅读更多
Never call virtual functions during construction or destruction
这是本条款的核心,不该在构造函数和析构函数期间调用virtual函数,因为存在不可预期的结果。为什么会这么说呢?首先看一下下面的例子:

首先有个基类base,其次Derived是其子类,print虚函数覆盖了父类函数。那么当Derived der创建的时候,会调用哪个print呢?下面上输出结果

从生成的结果可以看到,基类Base的print。基类型构造期间virtual函数绝对不会下降到派生类型阶层,也就是说virtual函数并不是virtual的。由于base class构造函数的执行更早于derived class构造函数,当base class构造函数执行时derived class的成员变量尚未初始化。如果此期间调用的virtual函数下降至derived class阶层,要知道derived class的函数几乎必然取用local成员变量,而那些成员变量尚未初始化。这将是一张通往不明确行为和彻夜调试大会串的直达车票。“要求使用对象内部尚未初始化的成分”是危险的代名词,所以C++不让你走这条路。

其实还有比上述理由根本的原因:在derived class对象的base class构造期间,对象的类型是base class而不是derived class。不只virtual函数会被编译器解析至(resolve to)base class,若使用运行期类型信息(runtime type information,例如dynamic_cast(见条款27)和typeid),也会把对象视为base class类型。本例之中,当derived 构造函数正执行起来打算初始化“derived 对象内的base class成分”时,该对象的类型是base 。那是每一个C++成分(见条款1)的态度,而这样的对待是合理的:这个对象呢你的“derived 专属成分”尚未初始化,所以面对它们,最安全的做法就是视它们不存在。对象在derived class构造函数开始执行前不会成为一个derived class对象。

相同道理也适用于析构函数。一旦derived class析构函数开始执行,对象内的derived class成员变量便呈现未定义值,所以C++的任何部分包括virtual函数,dynamic_casts等等也就那么看待它。

但是假设这样的调用virtual函数放在non-virtual函数里,而non-virtual函数则在构造函数和析构函数里调用,那么编译器很难检测到这样的情况。假设X定义的是pure virtual,,但运行时则会crash(如果你很愿意看的话)。

如下代码,就会出现问题


从图中可以看到,在pure virtual 函数被调用的时候,程序是会终止的。

所以确定你的构造函数和析构函数都没有(在对象被创建和销毁期间)调用virtual函数,而它们调用的所有函数也都服从同一约束

下面我们来讨论解决方案,像本条款书中所说:一种做法是在基类中内将函数改为non-virtual,然后要求derived class构造函数传递必要信息给基类构造函数,而后那个构造函数便可安全地调用non-virtual 函数。书中的例子有些不懂,编译不正确,等到我弄懂啦,在修正之。

请记住:

在构造和析构期间不要调用virtual函数,因为这类调用从不下降至derived class(比起当前执行构造和析构函数的那层)。

分享到:
评论

相关推荐

    Effective C++ 中文版

    条款09:绝不在构造和析构过程中调用Virtual函数 条款10:令Operator=返回一个referenceto this 条款11:在Operator=中处理“自我赋值” 条款12:复制对象时勿忘其每一个成分 3.资源管理 条款13:以对象管理...

    Effective C++(第三版)

    条款09:绝不在构造和析构过程中调用virtual函数 never call virtual functions during construction or destruction. 条款10:令operator= 返回一个reference to *this have assignment operators return a ...

    C++学习书籍——effective c++ 3rd(中英文)

    C++学习书籍——effective c++ 3rd(中英文)

    Effective C++学习笔记

    Effective C++学习笔记 没有时间看Effictive C++书的人可以看看这个笔记 总结出了重点啊 适合有c++基础的人阅读

    Effective C++

    Effective C++(编程的50个细节)着重讲解了编写C++程序应该注意的50个细节问题,书中的每一条准则描述了一个编写出更好的C++的方式,每一个条款的背后都有具体范例支持,书中讲的都是C++的编程技巧和注意事项,很多都...

    effective c++读书笔记

    effective c++读书笔记和总结 effective c++读书笔记和总结

    Effective Modern C++学习笔记

    《Effective Modern C++:改善C++11和C++14的42个具体做法(影印版)(英文版)》中包括以下主题:剖析花括号初始化、noexcept规范、完美转发、智能指针make函数的优缺点;讲解std∷move,std∷forward,rvalue引用和全局...

    Effective.C++.中文第二版.50条款doc文档.chm

    条款11: 为需要动态分配内存的类声明一个拷贝构造函数和一个赋值操作符 条款12: 尽量使用初始化而不要在构造函数里赋值 条款13: 初始化列表中成员列出的顺序和它们在类中声明的顺序相同 条款14: 确定基类有虚析构...

    Effective C++学习笔记.doc

    自己整理的侯捷版本<<Effective C++ 改善程序与设计的55个具体做法>> 学习笔记.

    Effective Modern C++:改善C++11和C++14的42个具体做法(中文版 + 英文版)

    《Effective Modern C++:改善C++11和C++14的42个具体做法(影印版)(英文版)》中包括以下主题:剖析花括号初始化、noexcept规范、完美转发、智能指针make函数的优缺点;讲解std∷move,std∷forward,rvalue引用和...

    More Effective C++

    条款34:如何在同一个程序中结合 C++ 和 C 270 Understand how to combine C++ and C in the same program 条款35:让自己习惯于标准 C++ 语言 277 Familiarize yourself with the language standard 推荐书目 285 ...

    effective C++读书笔记

    effective C++读书笔记,effective C++读书笔记,effective C++读书笔记

    EffectiveC++ and more Effective C++

    ·条款一:指针与引用的区别 ... ·条款二十五:将构造函数和非成员函数虚拟化  ·条款二十六:限制某个类所能产生的对象数量  ·条款二十七:要求或禁止在堆中产生对象  ·条款二十八:灵巧(smart)指针

    effective C++ 读书笔记

    effective C++ 很好 很不错 最好的C++进阶资料

    Effective C++跟more Effective c++

    Effective C++跟more Effective c++

    Effective C++(中文版).pdf

    Effective C++是世界顶级C++大师Scott Meyers的成名之作,初版于1991年。在国际上,这本书所引起的反响之大,波及整个计算机技术出版领域,余音至今未绝。几乎在所有C++书籍的推荐名单上,这部专著都会位于前三名。...

    Effective_Modern_C++_中文版

    想要彻底理解C++11和C++14,不可止步于熟悉它们引入的语言特性(例如,auto型别推导、移动语义、lambda表达式以及并发支持)。挑战在于高效地运用这些特性——从而使你的软件具备正确性、高效率、可维护性和可移植性...

    effective C++ 读书笔记 PPT

    摘录了《Effective C++》 (Scott Meyers 著)中有参考价值的编写代码建议,方面阅读

    Effective C++中文版第三版(带完整目录)(2-1)

    原因十分显明:scott meyers 极富实践意义的c++ 研讨方式,描述出专家用以产出干净、正确、高效代码的经验法则和行事法则——也就是他们几乎总是做或不做的某些事。  这本书不是读完一遍就可以束之高阁的快餐读物,...

Global site tag (gtag.js) - Google Analytics