quot;<<endl;
date1.showDate(); // 调用date1的showDate(),显示date1的数据
date1.setDate(2002,11,14); // 调用date1的setDate(),
// 重新设置date1的数据
cout<<"Date1 output2:"<<endl;
date1.showDate(); // 调用date1的showDate(),显示date1的数据
}
析构函数被调用的两种情况
1) 若一个对象被定义在一个函数体内,当这个函数结束时,析构函数被自动调用。
2) 若一个对象是使用new运算符动态创建,在使用delete释放时,自动调用析构函数。
【例2.13】 较完整的学生类例子
#include<iostream.h>
#include<string.h>
class Student {
public:
Student(char *name1,char *stu_no1,float score1); // 构造
函数
~Student(); // 析构函数
void modify(float score1); // 修改数据
void show(); // 显示数据
private:
char *name; // 学生姓名
char *stu_no; // 学生学号
float score; // 学生成绩
};
Student∷Student(char *name1,char *stu_no1,float score1)
{
name=new char[strlen(name1)+1];
strcpy(name,name1);
stu_no=new char[strlen(stu_no1)+1];
strcpy(stu_no,stu_no1);
score=score1;
}
Student∷~Student()
{
delete []name;
delete []stu_no;
}
void Student∷modify(float score1)
{ score=score1; }
void Student∷show()
{
cout<<"\n name: "<<name;
cout<<"\n stu_no: "<<stu_no;
cout<<"\n score: "<<score;
}
void main()
{
Student stu1("Liming","990201",90); // 定义类Student的对象stu1,
// 调用stu1的构造函数,初始化对象stu1
stu1.show(); // 调用stu1的show(),显示stu1的数据
stu1.modify(88); // 调用stu1的modify(),修改stu1的数据
stu1.show(); // 调用stu1的show(),显示stu1修改后的数据
}
name:Liming
stu_no:990201
score:90
name:Liming
stu_no:990201
score:88
缺省的析构函数
每个类必须有一个析构函数。
若没有显式地为一个类定义析构函数,编译系统会自动地生成一个缺省的析构函数
其格式如下:类名::析构函数名( ){ }
class string_data {
public:
string_data(char *)
{ str=new char[max_len];}
~string_data()
{ delete []str;}
void get_info(char *);
void sent_info(char *);
private:
char *str;
int max_len;
};
7. 调用构造函数和析构函数的顺序
1) 一般顺序
调用析构函数的次序正好与调用构造函数的次序相反:最先被调用的构造函数,其对应的(同一对象中的)析构函数最后被调用,而最后被调用的构造函数,其对应的析构函数最先被调用。
2) 全局对象
在全局范围中定义的对象(即在所有函数之外定义的对象),它的构造函数在所有函数(包括main函数)执行之前调用。在程序的流程离开其作用域时(如main函数结束或调用exit函数)时,调用该全局对象的析构函数。
3) auto局部对象
局部自动对象(例如在函数中定义的对象),则在建立对象时调用其构造函数。如果函数被多次调用,则在每次建立对象时都要调用构造函数。在函数调用结束、对象释放时先调用析构函数。
4) static局部对象
如果在函数中定义静态局部对象,则只在程序第一次调用此函数建立对象时调用构造函数一次,在调用结束时对象并不释放,因此也不调用析构函数,只在main函数结束或调用exit函数结束程序时,才调用析构函数。
8. 对象的生存期
对象按生存期的不同分为如下几种:
(1) 局部对象
- 当对象被定义时,调用构造函数,该对象被创建;当程序退出该对象所在的函数体或程序块时,调用析构函数,对象被释放。
- 局部对象是被定义在一个函数体或程序块内的,它的作用域限定在函数体或程序块内,生存期较短。
(2) 全局对象
- 当程序开始运行时,调用构造函数,该对象被创建;当程序结束时,调用析构函数,该对象被释放。
- 静态对象是被定义在一个文件中,它的作用域从定义是起到文件结束时为止。生存期较长。
(3) 静态对象
- 当程序中定义静态对象时,调用构造函数,该对象被创建;当整个程序结束时,调用析构函数,对象被释放。
- 全局对象是被定义在某个文件中,它的作用域包含在该文件的整个程序中,生存期是最长的。
(4) 动态对象
- 执行new运算符调用构造函数,动态对象被创建;用delete释放对象时,调用析构函数。
- 动态对象是由程序员掌握的,它的作用域和生存期是由new和delete之间的间隔决定的。
类的应用举例(例)
一圆形游泳池如图所示,现在需在其周围建一圆形过道,并在其四周围上栅栏。栅栏价格为35元/米,过道造价为20元/平方米。过道宽度为3米,游泳池半径由键盘输入。要求编程计算并输出过道和栅栏的造价。
#include <iostream>
using namespace std;
const float PI = 3.14159;
const float FencePrice = 35;
const float ConcretePrice = 20;
//声明类Circle 及其数据和方法
class Circle{
private:
float radius;
public:
Circle(float r); //构造函数
float Circumference() const; //圆周长
/*函数后的修饰符const表示该成员函数的执行不会改变类的状态,也就是说不会修改类的数据成员。 */
float Area() const; //圆面积
};// 类的实现
// 构造函数初始化数据成员radius
Circle::Circle(float r)
{
radius=r;
}
// 计算圆的周长
float Circle::Circumference() const
{
r