条款9:不要在构造和析构过程中调用virtual函数
如下是一个股票交易的例子:
class Transaction // 交易的基类
{
public:
Transaction();
virtual void logTransaction() const = ; // 用于记录交易日志
};
Transaction::Transaction()
{
logTransaction(); // 调用虚函数
} class BuyTransaction : public Transaction // 买进股票
{
virtual void logTransaction() const;
};
void BuyTransaction::logTransaction() const{ } class SellTransaction : public Transaction // 卖出股票
{
virtual void logTransaction() const;
};
void SellTransaction::logTransaction() const{ } int main()
{
BuyTransaction b; return ;
}
上述代码中执行BuyTransaction b时,会调用基类的构造函数,而基类的构造函数会调用一个虚函数来完成工作。但是该虚函数是否会调用派生类的对应函数呢?答案是否定的,解释如下:
1> 基类的构造是先于派生类的构造的。当基类的构造函数执行时,派生类中的成员尚未被初始化,如果允许基类构造期间调用派生类的函数,可能也会调用了没有初始化的“垃圾值”,导致不确定行为发生。
2> 基类构造期间,virtual函数的行为绝对不会伸到派生类中,因为此时构造的是基类,即此时构造的对象的类型是基类而非派生类,这点很重要。
但是有时我们在构造基类的时候又需要派生类中才有的参数信息,如何解决:
在基类中将logTransaction函数改为非虚函数,然后在构造派生类时将必要的参数传递到基类的构造函数中去,像如下这样:
#include <string> class Transaction // 交易的基类
{
public:
explicit Transaction(const std::string& logInfo);
void logTransaction(const std::string& logInfo) const; // 用于记录交易日志
};
Transaction::Transaction(const std::string& logInfo)
{
logTransaction(logInfo); // 调用非虚函数
}
void Transaction::logTransaction(const std::string& logInfo) const{ } class BuyTransaction : public Transaction // 买进股票
{
public:
BuyTransaction(const std::string& parameter) : Transaction(parameter){ }
}; int main()
{
BuyTransaction b("BT"); return ;
}
由上可知,如果基类构造时要使用派生类的信息,可以通过派生类构造函数的初始化列表传入相关参数,切不可调妄图调用虚函数实现,因为在构造基类期间其对象的类型是基类类型。
对于析构函数也是同样的道理,基类的析构总是在派生类析构后才进行,此时派生类的对象已经不存在了,而调用虚函数必然会引发一个不确定行为。当然你也可以将基类的虚函数实现后在析构函数中进行调用,但是这样的话,为什么不定义为非虚函数呢,虚函数的意义将不复存在了。
条款9:不要在构造和析构过程中调用virtual函数的更多相关文章
- Effective C++_笔记_条款09_绝不在构造和析构过程中调用virtual函数
(整理自Effctive C++,转载请注明.整理者:华科小涛@http://www.cnblogs.com/hust-ghtao/) 为方便采用书上的例子,先提出问题,在说解决方案. 1 问题 1: ...
- Effective C++ -----条款09:绝不在构造和析构过程中调用virtual函数
在构造和析构期间不要调用virtual函数,因为这类调用从不下降至derived class(比起当前执行构造函数和析构函数的那层).
- Effective C++ 条款九、十 绝不在构造和析构过程中调用virtual函数|令operator=返回一个reference to *this
1.当在一个子类当中调用构造函数,其父类构造函数肯定先被调用.如果此时父类构造函数中有一个virtual函数,子类当中也有,肯定执行父类当中的virtual函数,而此时子类当中的成员变量并未被初始 ...
- 条款9:绝不在构造和析构过程中调用virtual函数(Never call virtual functions during construction or destruction)
NOTE:在构造和析构期间不要调用virtual函数,因为这类调用从不下降至derived class(比起当前执行构造函数和析构函数的那层)
- 条款09:绝不在构造和析构过程中调用virtual函数
不该在构造函数和析构函数期间调用virtual函数,这一点是C++与jave/C#不同的地方之一. 假设有一个class继承体系,用来模拟股市交易如买进.卖出的订单等等.这样的交易一定要经过审计,所以 ...
- Effective C++ .09 不在构造和析构过程中调用virtual函数
看过C++对象模型的话就可以知道,在构造基类时,完整的vtable没有建立起来(表项没有被相应的子类函数替换),因而无法调用到子类的函数(即构造函数中的virtual函数是本类里的方法,不是virtu ...
- NO.8:绝不在构造或者析构过程中调用virtual函数
在构造和析构执行期间不要调用virtual函数,因为这类调用从不会下降至derived class(比起当前执行构造函数和析构函数) 如果在base class 构造函数或者析构函数调用virtual ...
- 【09】绝不在构造和析构过程中调用virtual方法
1.绝不在构造和析构过程中调用virtual方法,为啥? 原因很简单,对于前者,这种情况下,子类专有成分还没有构造,对于后者,子类专有成分已经销毁,因此调用的并不是子类重写的方法,这不是程序员所期望的 ...
- 绝不要在构造函数和析构过程中调用virtual函数
下面是一个用来塑模股市交易的类: derived的类的构造函数被调用,但是首先得调用基类Transaction的构造函数,但是在后面还得调用virrual函数,这个时候子类的对象的构造还没有完成,那么 ...
随机推荐
- javascript设计模式-享元模式
享元模式采用一个共享来有效的支持大量细小粒度的对象,避免大量有相同内容的类的开销(如内存耗费),共享一个元类. 应用场景:页面存在大量的资源密集型对象:他们具备一些共性,可以分离出公共操作的数据. 一 ...
- CHARINDEX用法
CHARINDEX返回字符串中指定表达式的起始位置. 语法CHARINDEX ( expression1 , expression2 [ , start_location ] ) 参数expre ...
- 【Hibernate 5】继承映射配置及多态查询
一.继承实现的三种策略 1.1,单表继承.每棵类继承树使用一个表(table per class hierarchy) -->本文主要介绍的继承策略 类继承树对应多个类,要把多个类的信息存放在一 ...
- json 對象的序列化
var a={x:1,y:2} s=JSON.stringify(a); //s="{"x":1,"y":2}" p=JSON.parse( ...
- Java设计模式(Design Patterns In Java)读书摘要——第1章 绪论
为何需要模式 模式是做事的方法,是实现目标,研磨技术的方法.通俗点说,模式是为了解决某个行业的某个问题的有效的方法或技艺. 为何需要设计模式 为了提升代码的水准,是代码变得简洁而易用.模式是一种思想, ...
- 用于MySql的SqlHelper
用于MySql的SqlHelper /// <summary> /// Title :MySqlHelper /// Author :WinterT /// Date :2015-1-8 ...
- 安装JAVA JDK注意事项
1 WIN8系统 安装JDK 我安装的是1.6版本, 64位的 : 2 安装好后 cmd 输入 java -version 正常 java 命令 正常 javac 命令不正常 提 ...
- CSS网页布局错位:CSS宽度计算
为什么计算宽度计算网页像素宽度是为了CSS网页布局整齐与兼容.常见的我们布局左右结构网页或使用padding.margin布局的时候将计算整页宽度,如果不计算无论是宽度过大过小就会出现错位问题. 怎么 ...
- winform中嵌入Ppt、Word、Excel
1.下载DsoFramer_KB311765_x86.exe 2.安装,默认路径安装C:\DsoFramer. 3.注册:开始菜单——>运行 输入:regsvr32 C:\DsoFramer\d ...
- WinForm界面布局控件WeifenLuo.WinFormsUI.Docking"的使用 (二)
WinForm界面布局控件WeifenLuo.WinFormsUI.Docking"的使用 (二) 编写人:CC阿爸 2015-1-29 今天我想与大家继续一起分享这一伟大的控件.有兴趣的同 ...