虚析构函数 和 纯虚析构函数
来源:互联网 发布:tensorflow mnist 例子 编辑:程序博客网 时间:2024/06/05 20:58
开始学C++了,所以又重拾以前学习过的相关概念…
析构函数是当一个对象的生命周期结束时,会自动执行析构函数。
析构函数的定义:
#ifndef __A_H__#define __A_H__class A{public: A(void); A(int a, int b); ~A(void); //析构函数private: int a; int b; int c;};#endif
虚析构函数与纯虚析构函数的定义(假定类名为A):
#ifndef __A_H__#define __A_H__class A{public: A(void); A(int a, int b); virtual ~A(void); //虚析构函数private: int a; int b; int c;};#endif
#ifndef __A_H__#define __A_H__class A{public: A(void); A(int a, int b); virtual ~A(void) = 0; //纯虚析构函数};#endif
其中定义了纯虚函数后,类A就成为了“抽象类”,它是不能有实例对象的。否则会报错:
“A”: 不能实例化抽象类
由于下列成员:
“A::~A(void)”: 是抽象的
一个类维护一个虚函数相关的表--vtable(__vfptr指向它),函数声明前面包含关键字“virtual”的函数,就会创建一个指向该函数的指针(函数指针)被存入vtable中。
虚函数表的作用是用来实现多态,但同时也带来了执行效率和额外内存空间的增加。
再来看虚析构函数,它所存在的意义:基类的指针指向派生类对象,用基类的指针删除派生类对象。
#include <iostream>using namespace std;class A{public: A() { cout <<"A..."<<endl; } ~A() { cout <<"~A..."<<endl; }};class B :public A{public : B() { cout <<"B..."<<endl; } ~B() { cout <<"~B..."<<endl; } };int main(){ A *a = new B(); delete a; return 0 ;}
输出:
A…
B…
~A…
派生类的析构函数未被调用,为什么呢?
派生类继承自基类,那么基类就只会存在于派生类中,直到派生类调用析构函数后。
假定:基类的析构函数调用比派生类要早,会造成的一种情况就是类成员不存在了,而类本身却还在,但是类存在的情况下,类成员应该还存在。所以这就矛盾了,所以派生类的析构函数会先被调用,基类的析构函数再被调用。
修改一下代码:
#include <iostream>using namespace std;class A{public: A() { cout <<"A..."<<endl; } virtual ~A() { cout <<"~A..."<<endl; }};class B :public A{public : B() { cout <<"B..."<<endl; } ~B() { cout <<"~B..."<<endl; } };int main(){ A *a = new B(); delete a; return 0 ;}
输出:
A…
B…
~B…
~A…
仅仅只是在基类的析构函数前面加了一个“virtual”,使它成为“虚析构函数”了,这就是“虚析构函数”存在的意义 :)
析构函数的作用并不是删除对象,而是撤销对象占用内存之前完成的一些清理工作…
//=========================================
总结:如果某个类不包含虚函数,那一般是表示它将不作为一个基类来使用。当一个类不准备作为基类使用时,就不要定义虚析构函数了,因为它会增加一个虚函数表,使得对象的体积翻倍,还有可能降低其可移值性。
所以基本的一条是:无故的声明虚析构函数和永远不去声明一样是错误的。
当且仅当类里包含至少一个虚函数的时候,才去声明虚析构函数。
抽象类是准备被用做基类的,基类必须要有一个虚析构函数,纯虚函数会产生抽象类,所以在想要成为抽象类的类里声明一个纯虚析构函数。
定义一个函数为虚函数,不代表该函数未被实现,只是为了来实现多态。
定义一个函数为纯虚函数,才表示函数未被实现 ,定义它是为了实现一个接口,起一个规范作用。继承抽象类的派生类要实现这个函数…
看下面的代码,如何输出:
//A.h#ifndef __A_H__#define __A_H__class A{public: A(void); A(int a, int b); virtual ~A(void); virtual void numAdd() = 0; virtual void f(); void ff();private: int a; int b; int c;};#endif
//A.cpp#include "A.h"#include <iostream>using namespace std;A::A(void){}A::A(int a, int b){ this->a = a; this->b = b; cout<<"a:"<<a<<" b:"<<b<<endl;}A::~A(void){ cout<<"~A"<<endl;}void A::f(){ cout<<"A::f()"<<endl;}void A::ff(){ cout<<"A::ff()"<<endl;}
//B.h#ifndef __B_H__#define __B_H__#include "a.h"class B :public A{public: B(void); ~B(void); virtual void numAdd(); void f(); virtual void ff();};#endif
//B.cpp#include "B.h"#include <iostream>using namespace std;B::B(void){}B::~B(void){ cout<<"~B"<<endl;}void B::numAdd(){}void B::f(){ cout<<"B::f()"<<endl;}void B::ff(){ cout<<"B:ff()"<<endl;}
main函数的定义:
//main()B b;A * a = &b;a->f();a->ff();return 0;
输出什么?
…
B::f()
A::ff()
//定义指向基类对象的指针a,当调用f()方法时,因为f为虚函数,所以调用了派生类的f(),输出B::f();
- 虚析构函数 和 纯虚析构函数
- c++的虚析构函数和纯虚析构函数
- 纯虚析构函数和非纯虚析构函数
- 虚函数和虚析构函数
- 虚函数和虚析构函数
- 虚析构函数、纯虚析构函数
- 虚析构函数,纯虚析构函数~~~
- 虚析构函数、纯虚析构函数、虚构造函数
- 虚析构函数、纯虚析构函数、虚构造函数
- 虚析构函数、纯虚析构函数、虚构造函数
- C++析构函数和虚析构函数。
- 虚析构函数和protected析构函数
- 虚构造函数和虚析构函数
- 析构函数和虚析构函数
- 析构函数和虚析构函数
- 虚析构函数和protected析构函数
- C++ 虚构造函数和虚析构函数
- 纯虚函数和虚析构函数
- UML中几种类间关系:继承、实现、依赖、关联、聚合、组合的联系与区别
- C++虚函数表详细解释及实例分析
- 通过 PCIE Inbound
- 8.cell重用
- “空”园三兄弟之nil和Nil及NUL
- 虚析构函数 和 纯虚析构函数
- 深度学习之Softmax回归
- 1011
- 修改 Linux 主机名
- spring原理
- windows客户端开发--判断一个文件夹中是否存在文件夹
- Opencv中的webCam
- 使用Nginx+FFMPEG搭建HLS直播转码服务器
- Linux下利用scandir判断是目录还是文件详解