析构函数也是一个特殊的成员函数。它的作用与构造函数相反。它的名字是在类名的前面加一个“~”符号。在C++中“~”是位取反运算符。当对象的生命结束时,会自动执行解析函数。以下几种情况会执行析构函数:

1.如果在一个函数中定义了一个对象,当这个函数被调用结束时,对象应该释放,在对象释放前自动执行析构函数。

2.static局部对象在函数调用结束时对象并不释放,因此也不调用析构函数,只在main函数结束或调用exit函数时,才调用staitic局部对象的析构函数。

3.如果定义了一个全局对象,则在程序的流程离开其作用域时(如main函数结束或exit函数),调用该全局对象的析构函数。

4.如果用new运算符动态的建立一个对象,当用delete运算符释放该对象时,先调用该对象的析构函数。

析构函数的作用并不是删除对象,而是在撤销对象占用的内存之前完成一些清理工作,使这部分内存可以被程序分配给新的对象使用。程序设计者事先设计好析构函数,以完成所需的功能,只要对象的生命结束,程序就自动执行析构函数来完成这些工作。

析构函数不返回任何值,没有函数类型,也没有函数参数。由于没有函数参数,它不能被重载。并且一个类中只能有一个析构函数。

析构函数还可以被用来执行“用户希望在最后一次使用对象之后所执行的任何操作”。例如输出有关的信息。这里说用户是指类的设计者。析构函数可以完成设计者多指定的任何操作。

想让析构函数完成任何工作,都必须在定义的析构函数中指定。

调用构造函数和析构函数的顺序

在一般情况下,调用析构函数的次序正好与调用调用构造函数的次序相反,最先被调用的构造函数,其对应的析构函数最后被调用,而而最后调用的构造函数,其对应的析构函数最先被调用。先构造的后析构,后构造的先析构。(并非任何时候都是按照这一原则进行的。会在作用域和存储类别的概念方面的不同)。对象可以在不同的作用域中定义,但是这是有区别的。

下面归纳一下是什么时候调用构造函数和析构函数:

1.在全局范围内定义的对象(即在所有函数之外定义的对象),它的构造函数在文件中所有函数(包括main函数)执行之前调用。但是如果一个程序中有多          个文件,而不同的文件都定义了全局对象,则这些对象的构造函数的执行顺序是不确定的。当main函数执行完毕或调用exit函数(此时程序终止)时,调          用析构函数。

2.如果定义的是局部自动对象(例如在函数中定义对象),则在建立对象时调用其构造函数。如果函数被调用多次,则在每次建立对象时都要调用构造函               数。在函数调用结束、对象释放时先调用析构函数。

3.如果在函数中定义静态static局部对象,则只在程序第一次调用此函数建立对象时调用构造函数一次,在调用结束时对像并不释放,因此也不调用析构            函数,只在main函数结束或调用exit函数结束程序时,才调用析构函数。

对象数组

在建立数组时,同样要调用构造函数,如果有50个元素,需要调用50次构造函数。在需要时可以在定义数组时提供实参以实现初始化。如果构造函数只有一      个参数,在定义数组时可以直接在等号后面的花括号里提供实参。如

Student stud[3]={60,70,80};

如果构造函数有多个参数,则不能在定义数组时直接提供所有实参的方法,因为一个数组有多个元素,对每个元素提供多个实参,如果在考虑到构造函数有默      认参数的情况,很容易造成实参和形参的对应关系不清晰,出现歧义。

那么,如果构造函数有多个参数,在定义对象数组时应该怎么实现初始化呢?答案:在花括号中分别写出构造函数并指定实参,如果构造函数有3个参数,分      别代表学号、年龄、成绩。则可以这样定义数组:

Student stud[3]={                                                   //定义对象数组

Student(1001,19,87);                                          // 调用第一个元素的构造函数,为他提供三个参数

Student(1002,19,78);                                          //调用第二个元素的构造函数,为他提供3个参数

Student(1003,18,79);                                          //  .......................

};

例子:

#include <iostream>
using namespace std;
class Box
{
public:
Box(int h,int w,int len):height(h),width(w),length(len){}
int volume();
private:
int height;
int width;
int length;
};

int Box::volume()
{
return (height*width*length);
}

int main()
{
Box a[3]={Box(10,12,15),Box(15,18,20),Box(16,20,26)};
cout<<"volume of a[0] is "<<a[0].volume()<<endl;
cout<<"volume of a[1] is "<<a[1].volume()<<endl;
cout<<"volume of a[2] is "<<a[2].volume()<<endl;
return 0;
}

对象指针

指向对象的指针,对象空间的起始地址就是对象的指针。

类名  *对象指针名;

指向对象成员的指针,对象有指针,存放对象初始地址的指针变量就是指向对象的指针变量。对象中的成员也有地址,存放对象成员地址的指针变量就是指         向对象成员的指针变量。

定义指向对象数据成员的指针变量的方法和定义指向普通变量的指针变量方法相同,例如:int *p;

定义指向对象数据成员和指针变量的一般形式:

数据类型名  *指针变量;

如果Time类的数据成员hour为公用的整数数据,则可以在类外通过指向对象数据成员的指针变量访问对象数据成员hour。

p1=&t1.hour;

cout<<*p1<<endl;

指向对象成员函数的指针,定义指向对象成员函数的指针变量的方法和定义指向普通函数的指针变量方法有所不同。下面是普通函数的指针变量的定义方           法:                       数据类型名  (*指针变量名)(参数列表);

如:void (*p)();                     //p是指向void型函数的指针变量

可以使它指向一个函数,并通过指针变量调用该函数。

p=fun;                                 //将fun函数的入口地址赋给指针变量p,p就指向了函数fun

(*p)();                                 //调用fun函数

成员函数与普通函数一个最根本区别是:它是类中的一个成员。编译系统要求在上面的赋值语句中,指针变量的类型必须与赋值号右侧函数的类型相匹配,要      求以下3方面都要匹配:1.函数参数的类型和参数个数;2.函数返回值的类型;3.所属的类。

应该按照如下形式定义指向成员函数的指针变量:

void(Time::*p2)();  //定义p2为指向Time类中公用成员函数的指针变量。

注意:(Time::*p2)两侧的括号不能省略,因为()的优先级高于*。

定义指向公用成员函数的指针变量的一般形式是:

数据类型名  (类名::*指针变量名)(参数列表);

可以让它指向一个公用成员函数,只需要把公用成员函数的入口地址赋给一个指向公用成员函数的指针变量即可。例如:

p2=&Time::get_time;

使指针变量指向一个公用成员函数的一般形式:

指针变量名=&类名::成员函数名;

例子:

#include <iostream>
using namespace std;
class Time
{
public:
Time(int,int,int);
int hour;
int minute;
int sec;
void get_time();
};

Time::Time(int h,int m,int s)
{
hour=h;
minute=m;
sec=s;
}

void Time::get_time()
{
cout<<hour<<":"<<minute<<":"<<sec<<endl;
}

int main()
{
Time t1(15,12,55);
int *p1=&t1.hour;
cout<<*p1<<endl;
t1.get_time();
Time *p2=&t1;
p2->get_time();
void(Time::*p3)();
p3=&Time::get_time;
(t1.*p3)();
}

关于类和对象的进一步讨论之析构函数 C++的更多相关文章

  1. 关于类和对象的进一步讨论 C++

    如果一个类中所有成员函数都是公用的,则可以在定义对象时对数据成员进行初始化: class  Time { public: hour; minute; sec; }; Time t1={14,15,23 ...

  2. oc语言学习之基础知识点介绍(二):类和对象的进一步介绍

    一.类.对象在内存中的存储 /* 内存分区: 栈:局部变量 堆:程序员自己写代码申请开辟的 程序员自己维护,编译器现在帮我们自动优化了,它在合适的给我们加上了释放空间的语句,所以我们现在写的对象不会造 ...

  3. C#学习笔记(十一):类和对象

    面向对象 为什么要面向对象: 1.和函数一样,把算法封装起来,方便复用 2.更好理解自己和别人写的代码 封装:数据.结构.逻辑的封装,方便复用 多态:同一个对象,同一种指令,不同的行为(反应) 继承: ...

  4. PHP -- 类和对象基础入门

         本文目录:    创建简单类和对象 继承 抽象类 接口 构造方法 析构函数     1. 创建简单类    创建一个People的类,在这里有四个要点说明一下: 第一个是在PHP中,访问属性 ...

  5. 《Java从入门到失业》第四章:类和对象(4.3):一个完整的例子带你深入类和对象

    4.3一个完整的例子带你深入类和对象 到此为止,我们基本掌握了类和对象的基础知识,并且还学会了String类的基本使用,下面我想用一个实际的小例子,逐步来讨论类和对象的一些其他知识点. 4.3.1需求 ...

  6. 一文讲全了Python 类和对象内容

    摘要:这是一个关于 Python 类和对象的全部内容. 本文分享自华为云社区<从零开始学python | Python 类和对象-面向对象编程>,原文作者:Yuchuan  . Pytho ...

  7. Objective-C Runtime 运行时之一:类与对象

    Objective-C语言是一门动态语言,它将很多静态语言在编译和链接时期做的事放到了运行时来处理.这种动态语言的优势在于:我们写代码时更具灵活性,如我们可以把消息转发给我们想要的对象,或者随意交换一 ...

  8. 解析Java类和对象的初始化过程

    类的初始化和对象初始化是 JVM 管理的类型生命周期中非常重要的两个环节,Google 了一遍网络,有关类装载机制的文章倒是不少,然而类初始化和对象初始化的文章并不多,特别是从字节码和 JVM 层次来 ...

  9. iOS RunTime运行时(1):类与对象

    Objective-C语言是一门动态语言,他将很多静态语言在编译和链接期做的事放到了运行时来处理.这种动态语言的优势在于:我们写代码更具有灵活性,如我们可以把消息转发给我们想要的对象,或者随意交换一下 ...

随机推荐

  1. comdlg32.dll

    dll的应用,目前还不知道要怎么查看dll里的功能,暂且试着用了一个, 下面的Declare 分32位office软件和64位,如果是64位,要在Declare 后面加上PtrSafe ,定义的Typ ...

  2. css3的基础知识

    transfrom的应用: 1.旋转:transform: rotate(30deg): 2.阴影效果:box-shadow: 10px 10px 5px #888888: 3.鼠标移入放大:tran ...

  3. golang bytes 包

    类型 []byte 的切片十分常见,Go 语言有一个 bytes 包专门用来解决这种类型的操作方法. bytes 包和字符串包十分类似.而且它还包含一个十分有用的类型 Buffer: import & ...

  4. [ZJOJ] 5772【NOIP2008模拟】今天你AK了吗

    Description AK:All kill“你为什么没背书?”“没有为什么,我就是没背书.”“……我去年买了个表,G—U—N!”头铁王InFleaKing把背书的时间都拿去列排列了......n= ...

  5. Django REST framework 渲染器、版本

    渲染器.版本: # settings.py REST_FRAMEWORK = { "DEFAULT_RENDERER_CLASSES": [ "rest_framewor ...

  6. Linux之ssh中XSHELL无法连接解决方案

    查漏补缺,理解概念,及时总结,互相交流,欢迎拍砖. 目前遇到的大致有以下几个问题分类: 网络是否连通.防火墙策略.DNS解析问题.端口是否开启.selinux是否开启-- 1.网络连通: 是否在同一网 ...

  7. 到Oracle官网下载 Oracle11 G 数据可和客户端操作

    1.准备一个Oracle的官网账号 用户名:541509124@qq.com 密码:LR4ever.1314 2.在搜索框中输入Oracle 11 G 3.点击Database Downloadds ...

  8. BZOJ 2097 [Usaco2010 Dec]Exercise 奶牛健美操

    [题意] 给出一棵树.现在可以在树中删去m条边,使它变成m+1棵树.要求最小化树的直径的最大值. [题解] 二分答案.$Check$的时候用$DP$,记录当前节点每个儿子的直径$v[i]$,如果$v[ ...

  9. 使用androidstudio 分析内存泄漏

    分析内存泄漏 http://www.jianshu.com/p/c49f778e7acf

  10. 3D全景之ThreeJs

    3D全景之ThreeJs 一.前言 随着H5越来越多的被应用到各个领域,3D也越来越频繁的出现在各个H5案例中,今天我们就来讨论一下3D全景的实现. 据百度百科上介绍:720全景是视角超过人的正常视角 ...