为多态基类声明virtual析构函数

non-virtual的析构函数

class Base{
public:
	Base(){
		cout << "Base" << endl;
	}
	~Base(){
		cout << "~Base" << endl;
	}
};
class Derive : public Base{
public:
	Derive(){
		cout << "Derive" << endl;
	}
	~Derive() {
		cout << "Derive" << endl;
	}
};
int main() {
	Base* bp = new Derive();
	delete bp;
	return 0;
}
  • 当我们删除(delete)一个指向派生类的基类指针时,如果该基类是non-virtual的析构函数,那么就会产生未定义行为。
  • 往往的结果是,Base的析构函数会被调用,而Derive的析构函数不会被调用。
  • 这是数据局部销毁和内存泄漏的方法之一(笑)。

为了使得堆上new的数据被正常释放,我们应该为用于多态的基类写一个virtual析构函数。

你可能会感到疑惑,基类和子类的析构函数名字不一样,为什么能是虚函数?

  • 编译器在编译时,会将所有的析构函数名称全部换成destructor,由此完成多态。

尽量不要为非Base类声明虚函数

  • 如果你的类不是用于Base类,那么最好不要为它写virtual的析构函数。
  • 因为一旦写入virtual的析构函数,编译器就会引入虚表指针等一系列手段,使得每个对象的大小增加。该类产生的每个对象的结构也会随之变化,这样该类的对象就无法用于相同声明的其他语言的对象(比如C语言,因为它们没有虚表指针)。
  • 这样降低了代码的移植性。
  • 所以,不要为非Base类写virtual析构函数。

怎么样判断你的类是否要作为Base呢?

  • 这里有一个小技巧,虽然不是每次都准。
  • 如果你的类中除了析构函数,没有virtual函数,那么就不要为析构函数增加virtual。

不要继承没有virtual析构函数的多态类

  • 实际上,正如我们上面所说,如果一个类没有写virtual函数,那么这个类的作者就不想让它作为用于多态的基类。
  • 如果你执意这样做,将该类(比如STL中的string,vector等)作为多态的Base类,那么结果往往是令人气急败坏的。

有时候纯虚函数是个好主意

  • 我们需要在多态的Base中写一个virtual析构函数。而Base类需要被继承。
  • 那么纯虚函数可能是一个好主意。纯虚函数所在的类自己无法创建对象,必须被继承。抽象类天生就是为了被继承。而且抽象类需要一个纯虚函数,那么不妨将析构函数写成纯虚函数。

小细节:

  • 纯虚函数一般是不用实现的。但是这里的纯虚析构函数需要给出实现(一般是空函数),因为编译器在析构时,先调用Derive的析构函数,之后会产生一条调用Base析构函数的语句,如果你不给出实现,那么编译器就会生气。
class Base{
public:
	Base(){
		cout << "Base" << endl;
	}
	virtual ~Base() = 0 {
		//用来 骗过 编译器
	}
};
class Derive : public Base{
public:
	Derive(){
		cout << "Derive" << endl;
	}
	~Derive() {
		cout << "Derive" << endl;
	}
};
int main() {
	Base* bp = new Derive();
	delete bp;
	return 0;
}
  • 某些类不是作为Base使用的,如string,那么就更不用说多态了。
  • 有些类即使用于Base,也不是用来提供多态功能,那么这种类也不需要virtual析构函数。
  • 只有用于多态的Base类才需要virtual析构函数。

本文主要来自:《EffectiveC++》

(全文完)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值