effective C++ 条款09

条款09  绝对不在构造和析构过程中调用virtual函数:

 

#include <iostream>

using namespace std;


class Base
{
public:
	Base()
	{
		Print();
	}

//	virtual void Print() const = 0;  //报错:pure virtual function was not defined

	virtual void Print()
	{
		cout<<"调用的是父类的print函数"<<endl;
	}

};

class Derived:public Base
{
public:
	Derived()
	{

	}
	
	virtual void Print()
	{
		cout<<"调用的是子类的print函数"<<endl;
	}


};


int main()
{

	Derived d; //输出的是调用父类的Print函数;
	return 0;
}

/*
当执行 Derived d;这句代码的时候,首先会有一个Derived构造函数被调用,但首先Base构造函数一定会被更早调用;
derived class 的base class 成分会在derived class自身成分被构造之前先构造好;
Base构造函数的最后一行调用virtual函数:Print()函数,这是引发惊奇的起点:这时候被调用的Print()函数是Base版本的
不是Derived版本的,即使目前建立的对象时Derived;
bass class构造期间virtual函数绝对不会下降到derived class阶层。取而代之的是,对象的作为就像隶属base类型一样;


由于base class构造函数的执行更早于derived class构造函数,当base class构造函数执行是derived class的成员变量尚未初始化。
如果此期间调用的virtual函数下降至derived class阶层,要知道derived 函数必然要调用derived的成员变量,而它的成员变量还没有初始化。


比上述理由更根本的原因是:
在derived class 对象的base class构造期间,对象的类型是base class 而不是derived class
*/


上面是原书的解释,其实我觉得可以这样解释:是virtual 虚函数指针的原因,虚函数指针直到子类对象最后被构建成功才会指向子类的虚函数表,而在父类的构造函数的时候,虚函数指针这个时候还在指向父类的虚函数表,所以调用的时候肯定是从父类虚函数表中找到Print()函数调用。

 

 

如果在父类当中需要子类的信息怎么做呢?那么就要求derived class 构造函数传递必要信息给Base构造函数:

#include <iostream>
#include <string>
using namespace std;

class Base
{
public:
	Base(int i)
	{
		this->i = i;
		cout<<i<<endl;
	}
	void log() const
	{
		cout<<"一个子类被创建"<<endl;
	}
private:
	int i;
};

class Derived : public Base
{
public:
	Derived(int j) : Base(j) //把子类的信息j 传送到父类
	{
		
	}
private:
	int j;
};

int main()
{
	Derived aa(7);
	aa.log();
	
	return 0;
}


 

总结:在构造和析构过程中不要调用virtual函数,因为这类调用从不下降至derived class。

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值