C++ 笔记(二) —— 不要在构造和析构函数中调用虚函数

ilocker:关注 Android 安全(新手) QQ: 2597294287

 1 class Transaction { //所有交易的 base class
 2 public:
 3     Transaction();
 4     virtual void logTransaction() const = 0; //做出一份因类型不同而不同的日志记录
 5     …
 6 }
 7 Transaction::Transaction() {
 8     …
 9     logTransaction();
10 }

derived class:

 1 class BuyTransaction : public Transaction {
 2 public:
 3     virtual void logTransaction() const;
 4     …
 5 }
 6 class SellTransaction : public Transaction {
 7 public:
 8     virtual void logTransaction() const;
 9     …
10 }

现在执行:

1 BuyTransaction b;

derived class 对象内的 base class 部分首先构造,所以 Transaction 构造函数先被调用。在 Transaction 构造函数中调用的 logTransaction 是 Transaction 的版本,而不是 BuyTransaction 的版本,即使创建的对象类型是 BuyTransaction。

base class 构造期间,virtual 函数绝不会下降到 drived classes 阶层,因为此时 drived class 的成员变量尚未初始化,如果 virtual 函数访问了未初始化的成员变量,就会导致不明确行为,c++ 不允许这种危险操作。

更明确的说:在derived class 对象的 base class 构造期间,对象的类型就是 base class,而不是 derived class,这一点对 RTTI (如 dynamic_cast、typeid) 同样有效。

同样的道理,在执行 base class 的析构函数时,derived class 的析构函数已执行完毕,derived class 的成员变量呈现未定义值,c++ 视他们不存在,此时对象就是一个 base class 对象。

在示例中,构造函数直接调用了 virtual 函数,此外还应注意构造函数和析构函数有没有间接调用 virtual 函数。

学习资料: 《Effective C++》

时间: 2024-08-09 16:26:21

C++ 笔记(二) —— 不要在构造和析构函数中调用虚函数的相关文章

EC笔记,第二部分:9.不在构造、析构函数中调用虚函数

9.不在构造.析构函数中调用虚函数 1.在构造函数和析构函数中调用虚函数会产生什么结果呢? #include <iostream> using namespace std; class cls1{ public: cls1(){ newMake(); }; ~cls1(){ deleteIt(); }; virtual void newMake(){ cout<<"cls1 make"<<endl; } virtual void deleteIt()

条款9:绝不要在构造以及析构函数中调用虚函数

在构造以及析构函数期间不要调用virtual函数,因为这类调用从不下降到derived class中.例如说下面这个例子: 1 class Transaction{ 2 public: 3 Transaction(); 4 virtual void logTransactions()s const = 0; 5 //... 6 }; 7 Transaction::Transaction() 8 { 9 //... 10 logTransaction(); 11 } 12 class BuyTra

绝不在构造和析构函数中调用 virtual 函数

看下面的这段代码,问 print调用的是基类还是派生类的版本? 答案是 基类... 可能大家会很惊讶,print不是virtual function 吗?为什么不是调用派生类的版本呢? 首先,当定义一个派生类的对象的时候, 由于 base class 构造函数的执行更早于 derived class构造函数, 所以当 base class constructor 调用的时候,派生类的成员尚未初始化(说明,这个时候真正的 虚函数表尚未完全初始化). 如果这个时候调用 派生类的函数(可能使用未初始化

在构造函数和析构函数中调用虚函数------新标准c++程序设计

在构造函数和析构函数中调用虚函数不是多态,因为编译时即可确定调用的是哪个函数.如果本类有该函数,调用的就是本类的函数:如果本类没有,调用的就是直接基类的函数:如果基类没有,调用的就是间接基类的函数,以此类推.例如: #include<iostream> using namespace std; class A { public: virtual void hello(){cout<<"A::hello()"<<endl;} virtual void

第八章:不要在构造和析构函数中使用虚函数

前言 本文将讲解一个新手C++程序员经常会犯的错误 - 在构造/析构函数中使用虚函数,并分析错误原因所在以及规避方法. 错误起因 首先,假设我们以一个实现交易的类为父类,然后一个实现买的类,一个实现卖的类为其子类. 这三个类的对象初始化过程中,都需要完成注册的这么一件事情 (函数).然而,各自注册的具体行为是不同的. 有些人会写出以下这样的代码: 1 class Transaction { 2 public: 3 Transaction(); // 父类构造函数 4 //...... 5 pri

不要在构造和析构函数中使用虚函数

前言 本文将讲解一个新手 C++ 程序员经常会犯的错误 - 在构造/析构函数中使用虚函数,并分析错误原因所在以及规避方法. 错误起因 首先,假设我们以一个实现交易的类为父类,然后一个实现买的类,一个实现卖的类为其子类. 这三个类的对象初始化过程中,都需要完成注册的这么一件事情 (函数).然而,各自注册的具体行为是不同的. 有些人会写出以下这样的代码: 1 class Transaction { 2 public: 3 Transaction(); // 父类构造函数 4 //...... 5 p

[C++]在构造函数及析构函数中调用虚函数

(ISO/IEC 14882:2011 section 12.7.4): Member functions, including virtual functions (10.3), can be called during construction or destruction (12.6.2).When a virtual function is called directly or indirectly from a constructor or from a destructor, inc

构造函数和析构函数中的虚函数

构造派生类对象时首先运行基类构造函数初始化对象的基类部分.在执行基类构造函数时,对象的派生类部分是未初始化的.实际上,此时对象还不是一个派生类对象. 撤销派生类对象时,首先撤销它的派生类部分,然后按照与构造顺序的逆序撤销它的基类部分. 在这两种情况下,运行构造函数或析构函数的时候,对象都是不完整的.为了适应这种不完整,编译器将对象的类型视为在构造或析构期间发生了变化.在基类构造函数或析构函数中,将派生类对象当作基类类型对象对待. 构造或析构期间的对象类型对虚函数的绑定有影响. 如果在构造函数或析

C++进阶--构造函数和析构函数中的虚函数

//############################################################################ /* 任何时候都不要在构造函数或析构函数中调用虚函数 */ class dog { public: string m_name; dog(string name) {m_name = name; bark();} virtual void bark() { cout<< "Woof, I am just a dog "