条款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函数,这个时候子类的对象的构造还没有完成,那么 ...
随机推荐
- 使用Servlet处理请求<http://blog.sina.com.cn/s/blog_5d3fb3cc0100ep9q.html>
一.GET和POST的区别 1.GET提交的是文本内容,规定其数据长度不超过255个字符.在GET方式提交的URL中会显示出提交的查询数据而却提交数据的缓存会在浏览器的URL历史状态中,这样我们往往在 ...
- poj2027
#include <stdio.h> int main(){ int n; int a,b; while(~scanf("%d",&n)){ while(n-- ...
- Ubuntu VPN连接设置
右击面板上的网络图标->VPN连接->配置VPN 点击“添加” 选择默认的PPTP VPN连接类型,点击“建立” 连接名称随便取一个.填入你到VPN网关和用户名.密码 点击“高级”,在“允 ...
- eclipse指定启动的jdk
原文:http://my.oschina.net/noday/blog/203987 到eclipse目录,打开eclipse.ini文件,在指定位置加入你的jdk相关文件(如下面示例配置中-vm配置 ...
- Filestream读取或写入文件
using System.IO;//引用 System.IO namespace filestream { public partial class Form1 : Form { public For ...
- webview 中 svg的坑
在这里不会详细介绍如何绘制svg图片,是讲一个很小的bug,看图 在这张图中,上面带有纹理和弧度的图片,原本是直接切了一张png的图片,但是由于是在app的登录注册的首页,那么这个35k的图片就会非常 ...
- 第一节 MongoDB介绍及下载与安装
引言 MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的.他支持的数据结构非常松散,是类似json的bjson格式,因此可以存储比较复杂的数据类 ...
- php文件上传的例子
1.上传表单 upload.html 程序代码 [html] view plaincopy <form enctype="multipart/form-data" actio ...
- 用开源中国(oschina)Git管理代码(整合IntelliJ 13.1.5)
简介 开源中国提供了Git服务(地址:http://git.oschina.net/),在速度上比国外的github要快很多.使用了一段时间,感觉很不错.oschina git提供了演示平台,可以运行 ...
- Index of my articles
65:一个表格说明RelativeLayout中的几个重要属性[Written By KillerLegend] (2013-10-16 21:59) 64:win7修改软件[授权给…]后面的名称 ( ...