为什么基类的析构函数是虚函数?

1.第一段代码

#include<iostream>
using namespace std;
class ClxBase{
public:
	ClxBase() {};
	~ClxBase() { cout << "Output from the destructor of class ClxBase!" << endl; };

	void DoSomething() { cout << "Do something in class ClxBase!" << endl; };
};

class ClxDerived : public ClxBase{
public:
	ClxDerived() {};
	~ClxDerived() { cout << "Output from the destructor of class ClxDerived!" << endl; };

	void DoSomething() { cout << "Do something in class ClxDerived!" << endl; };
};
int   main(){
	ClxDerived *p = new ClxDerived;
	p->DoSomething();
	delete p;
	return 0;
}

  

运行结果:

Do something in class ClxDerived!

Output from the destructor of class ClxDerived!

Output from the destructor of class ClxBase!

这段代码中基类的析构函数不是虚函数,在main函数中用继承类的指针去操作继承类的成员,释放指针P的过程是:先释放继承类的资源,再释放基类资源.

2.第二段代码

#include<iostream>
using namespace std;
class ClxBase{
public:
	ClxBase() {};
	~ClxBase() { cout << "Output from the destructor of class ClxBase!" << endl; };

	void DoSomething() { cout << "Do something in class ClxBase!" << endl; };
};

class ClxDerived : public ClxBase{
public:
	ClxDerived() {};
	~ClxDerived() { cout << "Output from the destructor of class ClxDerived!" << endl; };

	void DoSomething() { cout << "Do something in class ClxDerived!" << endl; }
};
int   main(){
	ClxBase *p = new ClxDerived;
	p->DoSomething();
	delete p;
	return 0;
}

  

输出结果:

Do something in class ClxBase!
Output from the destructor of class ClxBase!

这段代码中基类的析构函数同样不是虚函数,不同的是在main函数中用基类的指针去操作继承类的成员,释放指针P的过程是:只是释放了基类的资源,而没有调用继承类的析构函数.调用dosomething()函数执行的也是基类定义的函数.

一般情况下,这样的删除只能够删除基类对象,而不能删除子类对象,形成了删除一半形象,造成内存泄漏.

在公有继承中,基类对派生类及其对象的操作,只能影响到那些从基类继承下来的成员.如果想要用基类对非继承成员进行操作,则要把基类的这个函数定义为虚函数.

析构函数自然也应该如此:如果它想析构子类中的重新定义或新的成员及对象,当然也应该声明为虚的.

3.第三段代码:

#include<iostream>
using namespace std;
class ClxBase{
public:
	ClxBase() {};
	virtual ~ClxBase() { cout << "Output from the destructor of class ClxBase!" << endl; };
	virtual void DoSomething() { cout << "Do something in class ClxBase!" << endl; };
};

class ClxDerived : public ClxBase{
public:
	ClxDerived() {};
	~ClxDerived() { cout << "Output from the destructor of class ClxDerived!" << endl; };
	void DoSomething() { cout << "Do something in class ClxDerived!" << endl; };
};

int   main(){
	ClxBase *p = new ClxDerived;
	p->DoSomething();
	delete p;
	return 0;
}

  

运行结果:

Do something in class ClxDerived!
Output from the destructor of class ClxDerived!
Output from the destructor of class ClxBase!

这段代码中基类的析构函数被定义为虚函数,在main函数中用基类的指针去操作继承类的成员,释放指针P的过程是:只是释放了继承类的资源,再调用基类的析构函数.调用dosomething()函数执行的也是继承类定义的函数.

如果不需要基类对派生类及对象进行操作,则不能定义虚函数,因为这样会增加内存开销.当类里面有定义虚函数的时候,编译器会给类添加一个虚函数表,里面来存放虚函数指针,这样就会增加类的存储空间.所以,只有当一个类被用来作为基类的时候,才把析构函数写成虚函数.

时间: 2024-12-24 18:43:59

为什么基类的析构函数是虚函数?的相关文章

C++ 为什么设置基类的析构函数为虚函数

对象的析构函数调用顺序是从派生类到基类 那么如果基类的指针指向派生类的对象 还能正常的执行析构顺序吗 下面看一个类的声明 class Subject { public: ~Subject(); Subject(); }; class ConcreteSubject : public Subject { public : ConcreteSubject(); ~ConcreteSubject(); }; 创建基类的指针 并删除该对象 Subject * con = new ConcreteSubj

C++ 设置基类的析构函数为虚函数

析构函数是当一个对象的生命周期结束时自动调用的一个函数. 在下面的函数中,执行后会发现只有基类的析构函数被调用了,派生类的析构函数并没有被调用,导致对象没有被正常的释放,导致内存泄漏. 把基类的析构函数设置为虚函数,在执行动态调用时就会执向对象的析构函数. class Subject { public: ~Subject(); Subject(); }; class ConcreteSubject : public Subject { public : ConcreteSubject(); ~C

C++基类一定要写虚函数!!!

这是个提醒,算是吧! 如果详细原理过程,可能会有一个大篇幅.但这里不想多加赘述,只说说它的破坏力! 最近写了个图像处理框架,要做个基类来handle众多子类,写之前一直申称:要注意内存管理,写好析构函数. 谁知最后还是偏偏忘记了将基类析构函数virtual化,结果在操控基类释放内存的一段程序中,发现基类释放了,但attach到他上面的子类对象keep住没能free. 结果程序在集群上跑了几天,终于挂彩了...查了半天,终于发现base class的析构函数忘了加virtual,导致自己析构ok,

基类中定义的虚函数在派生类中重新定义时,其函数原型,包括返回类型、函数名、参数个数、参数类型及参数的先后顺序,都必须与基类中的原型完全相同 but------&gt; 可以返回派生类对象的引用或指针

您查询的关键词是:c++primer习题15.25 以下是该网页在北京时间 2016年07月15日 02:57:08 的快照: 如果打开速度慢,可以尝试快速版:如果想更新或删除快照,可以投诉快照. 百度和网页 http://bbs.csdn.net/topics/380238133 的作者无关,不对其内容负责.百度快照谨为网络故障时之索引,不代表被搜索网站的即时页面. 首页 精选版块 移动开发 iOS Android Qt WP 云计算 IaaS Pass/SaaS 分布式计算/Hadoop J

构造函数为什么不能为虚函数 &amp;amp; 基类的析构函数为什么要为虚函数

一.构造函数为什么不能为虚函数 1. 从存储空间角度,虚函数相应一个指向vtable虚函数表的指针,这大家都知道,但是这个指向vtable的指针事实上是存储在对象的内存空间的.问题出来了,假设构造函数是虚的,就须要通过 vtable来调用,但是对象还没有实例化,也就是内存空间还没有,怎么找vtable呢?所以构造函数不能是虚函数. 2. 从使用角度,虚函数主要用于在信息不全的情况下,能使重载的函数得到相应的调用.构造函数本身就是要初始化实例,那使用虚函数也没有实际意义呀.所以构造函数没有必要是虚

构造函数为什么不能为虚函数 &amp; 基类的析构函数为什么要为虚函数

一.构造函数为什么不能为虚函数 1. 从存储空间角度,虚函数对应一个指向vtable虚函数表的指针,这大家都知道,可是这个指向vtable的指针其实是存储在对象的内存空间的.问题出来了,如果构造函数是虚的,就需要通过 vtable来调用,可是对象还没有实例化,也就是内存空间还没有,怎么找vtable呢?所以构造函数不能是虚函数. 2. 从使用角度,虚函数主要用于在信息不全的情况下,能使重载的函数得到对应的调用.构造函数本身就是要初始化实例,那使用虚函数也没有实际意义呀.所以构造函数没有必要是虚函

从为什么要将基类的析构函数定义为虚函数谈起~~

 首先,做一个最简单的实验,在电脑上运行下面的代码,将会产生运行错误,这或许会使你百思不得其解: #include <iostream> using namespace std; class Base { private: int a; public: ~Base(){cout << "Base dtor..." << endl;} }; class Derived : public Base { private: int b; public: ~D

C++ Primer 学习笔记33_面向对象编程(4)--虚函数与多态(一):多态、派生类重定义、虚函数的访问、 . 和-&gt;的区别、虚析构函数、object slicing与虚函数

C++ Primer学习笔记33_面向对象编程(4)--虚函数与多态(一):多态.派生类重定义.虚函数的访问. . 和->的区别.虚析构函数.object slicing与虚函数 一.多态 多态可以简单地概括为"一个接口,多种方法",前面讲过的重载就是一种简单的多态,一个函数名(调用接口)对应着几个不同的函数原型(方法). 更通俗的说,多态行是指同一个操作作用于不同的对象就会产生不同的响应.或者说,多态性是指发出同样的消息被不同类型的对象接收时有可能导致完全不同的行为. 多态行分

[014]析构函数为虚函数的注意事项

1.当析构函数为虚函数时,其所有派生类的析构函数都将自动成为虚函数(不管是否被标记为virtual). 2.当基类的析构函数为虚函数时,如果对子类调用析构函数时,程序会先调用派生类的析构函数,然后再去调用基类的析构函数. 但如果基类的析构函数不是虚函数时,那么只会调用基类的析构函数. 例: class Base { virtual ~Base() {}; .... }; class Device :public Base { ~Device() {}; }; Base *pB = new Dev