本集的主要内容有:构造函数和析构函数
■C++在类说明中引进了构造函数
■构造函数在对象被创建时自动调用,为对象分配空间,对象所要执行的所有初始化工作都由构造函数自动完成。
■与构造函数相对对应的是析构函数。
■析构函数在一个对象消失时被自动调用,完成对象使用结束时所要进行的清理工作,释放被对象占用的资源。
1.规则
■构造函数的名字必须与其所属的类名相同,并声明为公有成员函数,并没有任何类型的返回值。
■构造函数可以访问类的所有数据成员,可以时内联函数,可以带有参数,还可以带默认的形参值。
■构造函数也可以重载,以提供初始化类对象的不同方法
口诀:
构造函数与类同名,无返回值,必须在公有段;
可内联,可重载,可带默认形参值
用构造函数定义圆类
#include <iostream>
using namespace std;
const double PI=3.14;
class Circle
{
private:
double radius;
public:
Circle(); //构造函数,类内声明
double area();
};
Circle::Circle() //构造函数类外实现
{
radius= 8;
cout<<"构造函数被调用,";
cout<<"员的半径设为8"<<endl;
}
double Circle::area()
{
double s= PI*radius*radius;
return s;
}
int main()
{
Circle cir; //构造函数在创建对象时自动调用
double s =cir.area();
cout<<"圆的面积为:"<<s<<endl;
}
运行
2.重载构造函数
■重载函数示例
#include <iostream>
using namespace std;
class Sum
{
private:
int num;
public:
Sum();
Sum(int a,int b);
void prnt();
};
Sum::Sum()
{
num=15;
cout<<"调用无参的构造函数,num="<<num<<endl;
}
Sum::Sum(int a,int b)
{
num=a+b;
cout<<"调用带参数构造函数"<<endl;
}
void Sum::prnt()
{
cout<<"调用一般成员函数"<<endl;
}
int main()
{
Sum s1;
Sum s2(3,5);
s1.prnt();
s2.prnt();
}
运行
#include <iostream>
using namespace std;
class Tdate
{
public:
Tdate(); //没有参数
Tdate(int b);
Tdate(int m,int d);
Tdate(int m,int d,int y);
protected:
int month;
int day;
int year;
};
Tdate::Tdate()
{
year=2010;
month=4;
day=15;
cout<<year<<"/"<<month<<"/"<<day<<endl;
}
Tdate::Tdate(int d)
{
year=2010;
month=4;
day=d;
cout<<year<<"/"<<month<<"/"<<day<<endl;
}
Tdate::Tdate(int m,int d)
{
year = 2010;
month = m;
day=d;
cout<<year<<"/"<<month<<"/"<<day<<endl;
}
Tdate::Tdate(int m,int d,int y)
{
year=y;
month=m;
day=d;
cout<<year<<"/"<<month<<"/"<<day<<endl;
}
int main()
{
Tdate aday;
Tdate bday(10);
Tdate cday(2,12);
Tdate dday(10,1,2010);
return 0;
}
运行
3.析构函数
■规则:
1.析构函数与所属的类同名,但其函数名前加一个逻辑非运算符“~”,表示构造函数的逆。
2.析构函数没有类型,没有形参。
一个类中只有可以一个析构函数。
3.析构函数必须是公有的。
口诀:析构函数类名前加~,无返回值,必须在公有段;
不接受任何参数。
示例
#include <iostream>
using namespace std;
class Sum
{
private:
int num;
public:
Sum();//构造函数
void prnt();//函数成员
~Sum();//析构函数
};
Sum::Sum()
{
num=15;
cout<<"调用构造函数,num="<<num<<endl;
}
Sum::~Sum()
{
cout<<"析构函数被调用"<<endl;
}
void Sum::prnt()
{
cout<<"调用一般成员函数"<<endl;
}
int main()
{
Sum s;
s.prnt();
}
运行
注意:
■C++语言规定,规定,任何一个类都必须有构造函数和析构函数。
■如果类中没有显示定义,则系统会提供一对默认的构造函数和析构函数。
考察构造函数与析构函数的调用顺序
#include <iostream>
using namespace std;
class Tdate
{
public:
Tdate();
Tdate(int d);
Tdate(int m,int d);
Tdate(int m,int d,int y);
~Tdate();
protected:
int month;
int day;
int year;
};
Tdate::Tdate()
{
year=2018;
month=4;
day=15;
cout<<year<<"/"<<month<<"/"<<day<<endl;
}
Tdate::Tdate(int d)
{
year=2018;
month=4;
day=d;
cout<<year<<"/"<<month<<"/"<<day<<endl;
}
Tdate::Tdate(int m,int d)
{
year =2018;
month = m;
day=d;
cout<<year<<"/"<<month<<"/"<<day<<endl;
}
Tdate::Tdate(int m,int d,int y)
{
year =2018;
month = m;
day=d;
cout<<year<<"/"<<month<<"/"<<day<<endl;
}
Tdate::~Tdate()
{
cout<<"析构函数";
cout<<year<<"/"<<month<<"/"<<day<<endl;
}
int main()
{
Tdate d1;
Tdate d2(10);
Tdate d3(2,12);
Tdate d4(10,1,2018);
}
总结:构造函数按对象创建的顺序被调用,析构函数顺序与构造顺序刚好相反。
4.拷贝构造函数
作用:用一个存在的对象来初始化另一个正创建的同类的对象,将一个已知对象的数据成员的值拷贝给正在创建的另一个同类的对象。
特点:
■该函数只有一个参数,并且是对某个对象的引用。
形式:
类内原型声明:
类名(类名 &对象名)
类外实现:
类名::类名(类名 &对象名)
{
......
}
示例
#include <iostream>
using namespace std;
class TPoint
{
private:
int x,y;
public:
TPoint(int a,int b){
x=a;y=b;
cout<<"普通函数被调用"<<endl;
}
TPoint(TPoint&p);//拷贝函数声明
~TPoint(){cout<<"析构函数被调用"<<endl;}
int Xcoord(){return x;}
int Ycoord(){return y;}
};
TPoint::TPoint(TPoint &p)
{
x=2*p.x;
y=2*p.y;
cout<<"拷贝构造函数被调用"<<endl;
}
int main()
{
TPoint P1(3,8);
TPoint P2(P1);
cout<<P2.Xcoord()<<","<<P2.Ycoord()<<endl;
}
构造函数的特点:
■函数与类同名
■没有返回值(void也没有)
■必须在公有段(创建对象时由系统自动调用)
■可以重载
析构函数的特点:
■函数名为类名前加~
■没有返回值(void也没有)
■必须在公有段(撤销对象时由系统自动调用)
■不接收任何参数(一个类只能有一个析构函数)