今天继续讲C++类和对象这块的内容:
1.类的6默认成员函数
1.1构造函数(无返回值)
构造函数是完成初始化工作的而不是创建对象的,这点一定要记清!!!
用户没写构造函数的话编译器是会自动生成的,但是用户一旦显式的定义了编译器将不再生成!!!
如果有创建多个对象,那么调用构造函数的顺序和你创建对象的顺序是一样的!!!
< font>
默认构造函数有三类:(默认构造函数就指的是不用参数就能调用的)
1)我们不写,编译器自动生成的
2)我们写了,但是是没有参数的
3)我们写的参数是全缺省的(一般这种要用的多一些)
例如下面:(默认构造函数只能存在一个)
class Date {
public :
// 1.自己写的无参构造函数
Date () {}
// 2.全缺省的构造函数
Date (int year, int month , int day )
{
_year = year ;
_month = month ;
_day = day ;
}
private :
int _year ;
int _month ;
int _day ;
};
void Test()
{
Date d1;
}
很多人会疑惑这里如果自己没写构造函数的话,创建对象时会调用系统默认生成的构造函数,但是这里的d1对象的值都是随机值,貌似看起来系统生成的这个默认构造函数没什么用啊?我想很多人都会有这个疑惑,其实是有用的,看下面这个例子:
class Time {
public:
Time()
{
cout << "Time()" << endl;
_hour = 0;
_minute = 0;
_second = 0;
}
private:
int _hour;
int _minute;
int _second;
};
class Date {
private:
// 基本类型(内置类型)
int _year;
int _month;
int _day;
// 自定义类型
Time _t;
};
int main()
{
Date d;
return 0;
}
运行结果:
你会发现当创建对象d时,编译器生成默认的构造函数会针对自定类型成员_t调用的它的默认成员函数,而且你也会发现上面的成员变量定义时前面都加了下划线,是为了和函数的参数区分开,以免引发冲突例如:year = year 这样的情况!
1.2析构函数(无参无返回值)
对象的销毁同样不是由析构函数去完成,析构函数只是完成一些资源的清理工作!!!
对象生命周期结束时,C++编译系统会自动调用析构函数
析构函数析构多个对象的顺序恰好和构造是相反的,类似于栈的性质
一般你没写析构函数,系统也会默认生成,但是如果遇到malloc或者new等开辟出来的空间就需要自己写析构函数来清理这些内存空间!!!< font>
1.3拷贝构造函数
拷贝构造函数就是用一个已经创建好的对象来初始化创建另一个对象。
拷贝构造函数是构造函数的一个重载形式。
若未显示定义,系统生成默认的拷贝构造函数。 默认的拷贝构造函数对象按内存存储按字节序完成拷贝,这种拷贝我们叫做浅拷贝,或者值拷贝。< font>
class Date
{
public:
Date(int year = 1900, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
Date(const Date& d) //拷贝构造函数
{
_year = d._year;
_month = d._month;
_day = d._day;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1;
Date d2(d1);
return 0;
}
拷贝构造函数里的参数加const是为了让d2能和d1的值一样,因为使用d1的值去拷贝构造出一个一模一样的对象d2,为了不改变值,所以必须加const,加&符是为了避免引发无穷递归。< font>
如下图所示:
因为如果不加&符就属于值拷贝,在这里调用拷贝函数的时候,拷贝构造函数的参数就是一个临时变量,就又需要调用拷贝构造函数来生成,这样将会如此递归调用下去,,,,程序就会陷入死循环!
1.4赋值运算符重载
首先先说下运算符重载:
C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有其返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。
函数名字为:关键字operator后面接需要重载的运算符符号。
函数原型:返回值类型 operator操作符(参数列表)
作为类成员的重载函数时,其形参看起来比操作数数目少1成员函数的 操作符有一个默认的形参this,限定为第一个形参 。
.* 、:: 、sizeof 、?: 、. 注意以上5个运算符不能重载。这个经常在笔试选择题中出现。 < font>
bool operator==(const Date& d2)
{
return _year == d2._year
&& _month == d2._month
&& _day == d2._day;
}
上面这样重载了==,就可以判断两个日期对象是否是相等的了!
赋值运算符的重载:
Date& operator=(const Date& d)
{
if(this != &d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
}
赋值运算符主要有四点:
1.参数类型
2. 返回值
3. 检测是否自己给自己赋值
4. 返回*this
一个类如果没有显式定义赋值运算符重载,编译器也会生成一个,完成对象按字节序的值拷贝。
const成员函数:
将const修饰的类成员函数称之为const成员函数,const修饰类成员函数,实际修饰该成员函数隐含的this 指针,表明在该成员函数中不能对类的任何成员进行修改。
void Display() const
{
cout<<_year<<"-"<<_month<<"-"<<_day<<endl;
}
void Display(const Date *this)
{
cout<<_year<<"-"<<_month<<"-"<<_day<<endl;
}
上面两个函数是一样的,表示的意思都是不能修改*this这个对象的值!