關於類的6個默認成員函數
一、前言知識
1.this指針
a.this指針式一個指針,它時時刻刻指向一個實例;
b.this指針的類型是:類類型* const;
c.this指針並不是對象本身的一部分,不影響sizeof的結果;
d.this指針是類成員函數的第一個默認隱含參數,編譯器會自動維護和傳遞;
2.引用
a.引用不是新定義一個變量,而是給已存在的變量取了一個別名,所以編譯器不會爲引用變量開闢內存空間,它和它引用的變量共用同一塊內存空間;
b.引用的格式:類型& 變量(對象名)=引用變量名;
例如:int&ra=a;a和ra的類型相同。
c.引用在定義時必須初始化;
d.一個變量可以有多個引用;
e.引用一旦綁定了一個實體,就不能再改變爲其他變量的引用;
f.函數中不要返回棧內存的引用;
例如:int&Add(int& left,int& right)
{
int result=left+right;
return result;
}
g.使用引用可以起到和指針一樣的作用,既可以改變實參的值,也可以改變形參的值。
二、類的六個成員函數
1.構造函數:是一個特殊的成員函數,名字與類名相同,創建類類型對象時,由編譯器自動調用,在對象的生命週期內有且只調用一次,以保證每個數據成員都有一個合適的初始值。
#include<iostream>
using namespace std;
class Date
{
public:
Date()//第一種情況可以不傳參數
{}
Date(int year, int month, int day)//第二種情況可以帶參數
{}
Date(int year = 2017, int month = 2, int day = 18)//第三種情況是可以給參數帶缺省值
{}
Date(int year, int month, int day)//第四種情況是給出初始化列表,初始化列表只有構造函數有
:_year = year
, _month = month
, _day = day
{}
private:
int _year;
int _month;
int _day;
};
構造函數的特點:
a.函數名與類名相同;
b.沒有返回值;
c.有初始化列表,但是不強制使用;
e.新對象被創建時,由編譯器自動調用,且在對象的生命週期內只調用一次;
f.構造函數可以重載,實參決定調用哪個構造函數;
g.引用數據成員、const數據成員、類類型成員必須要放在初始化列表中初始化;
h.explcit修飾構造函數,抑制由構造函數定義的隱式轉換。
2.拷貝構造函數:只有單個形參,而且該形參是對本類類型對象的引用(常用const修飾),這樣的構造函數稱爲拷貝構造函數。它是特殊的構造函數,創建對象時使用已存在的同類對象來進行初始化,由編譯器自動調用。
#include<iostream>
using namespace std;
class Date
{
public:
Date(const Date& d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
private:
int _year;
int _month;
int _day;
};
拷貝構造函數的特點:
a.它是構造函數的重載;
b.它的參數必須使用同類類型對象的引用傳遞。
使用場景:a.對象實例化對象 b.傳值方式作爲函數的參數 c.傳值方式作爲函數返回值
3.析構函數:與構造函數功能相反,在對象被銷燬時,由編譯器自動調用,完成類的一些資源清理和汕尾工作。
形如:~Date()
{}
析構函數特點:
a.析構函數無參數無返回值;
b.一個類有且只有一個析構函數;
c.析構函數體內並不是刪除對象,而是做一些清理工作。
4.賦值操作符重載函數
操作符重載函數形如:返回類型 operator 操作符(參數列表)
這裏以一個Date類來說明:
#include<iostream>
using namespace std;
class Date
{
public:
bool JudgeLeapyear(int year)
{
if ((year % 400 == 0) || ((year % 4 == 0) && (year % 100 != 0)))
{
return true;
}
else
{
return false;
}
}
int GetDay(int year, int month)
{
int days[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
if (JudgeLeapyear(year) && (month == 2))
{
days[2] += 1;
}
return days[month];
}
Date(int year, int month, int day)
:_year(year)
, _month(month)
, _day(day)//初始化列表,只有構造函數纔有
{
cout << "Date(int year, int month, int day)" << this << endl;
}
Date(const Date& d)
{
_year = d._year;
_month = d._month;
_day = d._day;
cout << "Date(const Date& d2)" << endl;
}
~Date()
{
cout << "~Date" << endl;
}
bool operator<(const Date& d)
{
return (_year < d._year) || ((_year == d._year) && (_month < d._month))
|| ((_year == d._year) && (_month == d._month) && (_day<d._day));
}
bool operator>(const Date& d)
{
return !((*this < d) || (*this == d));
}
bool operator<=(const Date& d)
{
return ((*this < d) || (*this == d));
//return !(*this>d);
}
bool operator>=(const Date& d)
{
return ((*this > d) || (*this == d));
//return !(*this<d);
}
bool operator==(const Date& d)
{
return (_year == d._year) && (_month == d._month) && (_day == d._day);
}
bool operator!=(const Date& d)
{
return !(*this == d);
}
Date operator+(int day)//求day天后的日期
{
Date temp(*this);
if (day < 0)
{
return ((*this) - (0 - day));
}
else
{
temp._day = temp._day + day;
if (temp._day>GetDay(temp._year, temp._month))
{
temp._day = temp._day - day;
if (temp._month == 12)
{
temp._year = temp._year + 1;
temp._month = 1;
}
else
{
temp._month++;
}
}
// else
//{
return temp;
//}
}
}
Date operator-(int day)//求day天前的日期
{
Date temp(*this);
if (day < 0)
{
return ((*this) + (0 - day));
}
else
{
temp._day = temp._day - day;
if (temp._day <= 0)
{
if (temp._month == 1)
{
temp._year = temp._year - 1;
temp._month = 12;
}
else
{
temp._month--;
}
temp._day = GetDay(temp._year, temp._month) - (0 - temp._day);
}
//else
// {
return temp;
// }
}
}
Date& operator++()//前置++
{
_day = _day + 1;
return *this;
}
Date& operator++(int)//後置++
{
Date temp(*this);
_day = _day + 1;
return *this;
}
Date& operator--()//前置--
{
_day = _day - 1;
return *this;
}
Date& operator--(int)//後置--
{
Date temp(*this);
_day = _day - 1;
return *this;
}
friend ostream& operator<< (ostream& out, const Date& d)
{
out << d._year << "--" << d._month << "--" << d._day << " " << endl;
return out;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1(2016, 1, 5);
Date d2(2015, 12, 20);
int result1 = d1<(d2);
int result2 = d1>(d2);
Date d3 = d1 + 10;
int result3 = d1 - d2;
Date d4 = d1++;
Date d5 = d1 + 1;
system("pause");
return 0;
}
5.取地址操作符重載
6.const修飾的取地址操作符重載
class CTest
{
public:
CTest* operator&()
{
return this;
}
const CTest* operator & ()const
{
return this;
}
};