类有6个默认成员函数:
1.构造函数
2.拷贝构造函数
3.析构函数
4.赋值操作符重载
5.取地址操作符重载
6.const修饰的取地址操作符重载
一:构造函数
作用:对私有成员变量进行初始化。 Date();
公有成员函数,仅在定义对象时自动执行一次。
特点:
1.函数名与类名相同。
2.对象构造时自动调用。
3.无返回值。
4.可以重载。
5.可以在类内外定义。
6.如果无构造函数,编译器自动产生一个缺省的构造函数。
7.无参和全缺省值的构造函数都认为是缺省构造函数,并且缺省构造函数之能有一个。
class Date
{
public:
Date() //缺省构造函数
{};
Date(int year,int month,int day)//构造函数
{
_year=year;
_month=month;
_day=day;
}
private:
int _year;
int _month;
int _day;
};
二:拷贝构造函数
作用:创建对象时使用同类对象来进行初始化。Date(const Date&t)
特点:
1.是构造函数的一个重载。
2.必须使用引用传参,传值会无穷递归调用。
3.未定义时,编译器会自动生成一个默认缺省拷贝构造函数,缺省的拷贝构造函数会依次拷贝类成员进行初始化。
Date d1;
Date d2=d1; 等价
Date d3(d1);
class Date
{
public:
Date()//构造函数
{}
Date(int year,int month,int day) //构造函数
{
_year=year;
_month=month;
_day=day;
};
Date(const Date&t) //拷贝构造函数
{
_year=t._year;
_month=t._month;
_day=t._day;
}
private:
int _year;
int _month;
int _day;
};
拷贝构造函数必须使用引用传参的原因
使用代码:
class Date
{
public:
Date()//构造函数
{}
Date(int year,int month,int day) //构造函数
{
_year=year;
_month=month;
_day=day;
};
Date(const Date t) //拷贝构造函数
{
_year=t._year;
_month=t._month;
_day=t._day;
}
private:
int _year;
int _month;
int _day;
};
Funtest()
{
Date d1(2111,2,2);
Date d2=d1;
}
Date d2=d1;
调用拷贝构造函数 Date(const Date t); 相当于 d2(d1);
因为传参过程中是值传递,所以需要创建一个临时变量来存放d1的值,假设此时的临时变量名为 d’;
此时要用d1来初始化d’,相当于d’(d1),此时需要调用拷贝构造函数 Date(const Date t);
因为因为传参过程中是值传递,所以需要创建一个临时变量来存放d1的值,假设此时的临时变量名为 d”;此后所有的过程相同,程序将陷入一个无穷递归的过程。
所以拷贝构造函数传参过程中需要引用传参。
一 – 二 :类成员的初始化方式
1.构造函数内进行赋值
2.初始化列表
以一个冒号开始,接着一个逗号分隔数据列表;
Date(…,const Date&t)
:_year(year)
,_month(month)
,_day(day)
{}
其中,成员变量按照声明顺序依次初始化;
必须使用初始化列表的变量:
(1).常量成员变量
(2).引用类型成员变量
(3).没有缺省构造函数的类成员变量
三:析构函数 ~Date()
作用:在对象声明周期结束时,调用的函数。(清除类本身分配的资源);
特点:
1.函数名在类名前加上~;
2.无参数无返回值;
3.一个类只能有一个析构函数,若未定义,系统默认生成析构函数;
4.自动调用;
5.析构函数并非删除对象,而是做一些清理工作(释放空间);
class Array()
{
public:
~Array(){ //析构函数 清理工作
if(_ptr){
free(_ptr);
_ptr=0;
}
}
private:
int *_ptr;
}
四.重载:
作用:增强程序的可读性 关键词 :operator
特点:
1.operator+合法的运算符构成函数名;
2.重载运算符,不可以改变,操作数个数,结合性;
3.不能重载的运算符 “*/ ” “:: ” “?: ” “. “;
输入输出运算符的重载:
对于自定义的类,不能直接通过
cout<<Date或cin>>Date;
通过重载输入输出运算符,让自定义的类也支持这样的操作;
friend ostream &operator<<(ostream &os,const Date &stu);
friend istream &operator>>(istream &is,const Daet &stu);
cout并不特殊,是预先定义好了的ostream类的对象
输出运算符重点:
输出运算符的第一个形参时一个非常量(自流写入内容会改变状态)的ostream对象的引用(流对象不支持复制)。
第二个参数一般来说是一个常量(打印不需要改变对象内容)的引用(避免复制实参)。
输出函数应尽量避免格式化的操作。
输入运算符重点:
输入运算符的第一个形参是将要读取的流的引用。
第二个形参是将要读入到的非常量对象的引用。
输入运算符必须处理输入可能失败的情况。(输入数据与类型不匹配)(流达到文件末尾)
声明为友元函数。
输入,输出运算符都必须是非成员函数;
class Date
{
public:
//构造函数,列表初始化
Date()
:_year(0)
, _month(0)
,_day(0) {}
//重载输出运算符
friend ostream &operator<<(ostream &os, const Student &stu); //声明为友元
//重载输入运算符
friend istream &operator >> (istream &is, Student &stu);
private:
int _year;
int _month;
int _day;
};
ostream &operator<<(ostream &os, const Student &stu)
{
os << Date._year << " " << Date._month<<" "<<Daet._day;
return os;
}
istream &operator >> (istream &is, Student &stu)
{
is >>Date._year>>Date._month>>Date._day;
//输入判断
if (!is)
stu = Date(); //如果失败,默认初始化
return is;
}
四.赋值运算符重载
作用: 对一个已存在的对象进行拷贝赋值;
Date &operator = (const Date &d);
class Date()
{
public:
Date(int year,int month,int day)
:_year(year)
,_month(month)
,_day(day)
{}
Date &operator(const Date &t){
if(this!=d){
this->_year=d._year;
this->_month=d._month;
this->_day=d._day;
}
return *this;
}
private:
int _year;
int _month;
int _day;
};
FunTest(){
Date d1(2001,1,1);
Date d2;
d2=d1;
}
四–五 :友元
友元函数: 关键词: friend
友元函数可以直接访问类的私有成员,是定义在类外的函数。
友元函数不属于类的成员函数,但需要在类内声明(可以在类内的任何地方声明,所以友元函数不受访问限定符的限制),声明时要加上关键字friend。
友元类:
整个类都可以是另一个类的友元函数,都可访问另一个类中的成员。
class Time
{
friend class Date;
//Date是 Time的友元,所以Date可以访问Time的所有成员
private:
int _hour;
int _minute;
int _second;
};
class Date
{
public:
void Display(){
cout<<"year"<<_year<<endl;
cout<<"month"<<_month<<endl;
cout<<"day"<<_day<<endl;
cout<<"hour"<<_hour<<endl;
cout<<"minute"<<_minute<<endl;
cout<<"second"<<_second<<endl;
}
private:
int _year;
int _month;
int _day;
};
友元关系是单向的,不具有交换性。
友元关系无法传递。
友元关系无法继承。
五.取地址操作符重载 ———- Date * operator&();
六.const修饰的取地址操作符重载;const Date * operator&();
这两个默认成员函数一班不需要重载。
七.const修饰的成员函数
在成员函数后面加上const,用来修饰this指针所指向的对象,保证此对象在函数内不会被改变。
this指针的形式为,const Date *this;
const修饰成员函数后,变为 const Date * const this;
class Date
{
public:
void SetDate(int yar,int month,int day) const {
_year=year;
_month=month;
_day=day;
}
private:
int _year;
int _month;
int _day;
};
此时的对象的成员将无法被SetDate()函数更改。
八.类的静态成员
1.static修饰的成员,称为静态类成员。
2.类的静态成员被该类型的所有对象所共享。
3.静态成员函数不会生成this指针,所以可以使用类型::作用域访问符调用静态成员函数。