类成员函数解析
?
1、? 構(gòu)造函數(shù):
(1)??????定義:是一個(gè)特殊的成員函數(shù),名字與類(lèi)名相同,創(chuàng)建類(lèi)類(lèi)型對(duì)象時(shí),由編譯器自動(dòng)調(diào)用,在對(duì)象的生命周期內(nèi)只且只調(diào)用一次,以保證每個(gè)數(shù)據(jù)成員都有一個(gè)合適的初始值。
(2)??????特性:
1、函數(shù)名與類(lèi)名相同。
2、沒(méi)有返回值。
3、有初始化列表(可以不用)。
4、新對(duì)象被創(chuàng)建,由編譯器自動(dòng)調(diào)用,且在對(duì)象的生命期內(nèi)僅調(diào)用一次。
5、構(gòu)造函數(shù)可以重載,實(shí)參決定了調(diào)用那個(gè)構(gòu)造函數(shù)。
6、如果沒(méi)有顯式定義時(shí),編譯器會(huì)提供一個(gè)默認(rèn)的構(gòu)造函數(shù)。
7、無(wú)參構(gòu)造函數(shù)和帶有缺省值得構(gòu)造函數(shù)都認(rèn)為是缺省構(gòu)造函數(shù),并且缺省構(gòu)造函數(shù)只能有一個(gè)。
(3)分類(lèi):
?
無(wú)參構(gòu)造函數(shù):如果沒(méi)有顯式的定義一個(gè)構(gòu)造函數(shù),系統(tǒng)將默認(rèn)合成一個(gè)無(wú)參構(gòu)造函數(shù),參數(shù)為空,什么都不做。
?
顯式的定義一個(gè)無(wú)參構(gòu)造函數(shù),如下例:
??? Time()
??? {
?????? cout<<"Time(int intint )"<<endl;
??? }
?
普通構(gòu)造函數(shù)(也稱重載構(gòu)造函數(shù)):
class Time
{
public:
??? Time(int h, int m, int s)
??? {
?????? _hour = h;
?????? _minute = m;
?????? _second = s;
?????? cout<<”Time(int, int, int)”<<endl;
??? }
private:
??? int _hour;
??? int _minute;
??? int _second;
};
?
?
系統(tǒng)默認(rèn)合成的構(gòu)造函數(shù):在A類(lèi)有缺省的構(gòu)造函數(shù),B類(lèi)沒(méi)有顯示的定義構(gòu)造函數(shù),B類(lèi)中含有A類(lèi)類(lèi)型成員,此時(shí)系統(tǒng)默認(rèn)合成構(gòu)造函數(shù)。
class Time
{
public:
?
??? Time()
??? {
?????? cout<<"Time(int intint )"<<endl;
??? }
private:
??? int _hour;
??? int _minute;
??? int _second;
};
class Date
{
private:
??? int _year;
??? int _month;
??? int _day;
??? Time t;
?
};
?
?
運(yùn)行結(jié)果:
?
?
?
?
初始化列表:
以一個(gè)冒號(hào)開(kāi)始,接著是一個(gè)以逗號(hào)分隔的數(shù)據(jù)成員列表,每個(gè)數(shù)據(jù)成員后面跟一個(gè)放在園括號(hào)中的初始化式。
classDate
{
public:
??? ?Date(int year = 1, int month = 2, int day = 3)
?????? :_year(year),
?????? _month(month),
?????? _day(day)
?????? {
?????????? cout<<"Date(int, int, int)"<<endl;
?????? }
private:
??? int _year;
??? int _month;
??? int _day;
?
};
初始化順序:
?
1、初始化列表僅用于初始化數(shù)據(jù)成員,并不指定這些數(shù)據(jù)成員的初始化順序,數(shù)據(jù)成員在類(lèi)中定義順序就是在參數(shù)列表中的初始化順序。
?
2、每個(gè)成員在初始化列表中只能出現(xiàn)一次,盡量避免使用成員初始化成員,成員的初始化順序最好和成員的定義順序保持一致。
?
類(lèi)中包含以下成員必須要放在初始化列表中初始化:
class Time
{
public:
??? //Time()
??? //{}
??? Time(int h, int m, int s)
??? {
?????? cout<<"Time(int intint )"<<endl;
??? }
private:
??? int _hour;
??? int _minute;
??? int _second;
};
?
class Date
{
public:
??? ?Date(int year, int month, int day)
?????? :_year(year),
?????? _month(month),
?????? _day(day),
?????? t(0, 0, 0)
?????? {
?????????? cout<<_year<<"-"<<_month<<"-"<<_day<<endl;
?????? }
private:
??? int _year;
??? int _month;
??? int _day;
??? const int a;
??? int& b;
};
1、引用數(shù)據(jù)成員
2、const數(shù)據(jù)成員
?
?
3、類(lèi)類(lèi)型成員(該類(lèi)沒(méi)有缺省的構(gòu)造函數(shù)):Time類(lèi)中沒(méi)有缺省的構(gòu)造函數(shù)(無(wú)參構(gòu)造函數(shù),有參數(shù),但有缺省的構(gòu)造函數(shù)),要調(diào)用Date類(lèi)創(chuàng)建對(duì)象,則類(lèi)內(nèi)的成員都要初始化,Date類(lèi)中含有Time類(lèi)類(lèi)型成員,只能在初始化列表內(nèi)進(jìn)行初始化
?
?
?
?
?
?
2、? 拷貝構(gòu)造函數(shù)
顯式的定義拷貝構(gòu)造函數(shù):
class Date
{
public:
??? ?Date(int year = 1, int month = 2, int day = 3)
?????? :_year(year),
?????? _month(month),
?????? _day(day)
?????? {
?????????? cout<<"Date(int, int,int)"<<endl;
?????? }
??? ?Date(const Date &d)
?????? :_year(d._year),
?????? _month(d._month),
?????? _day(d._day)
??? ?{
?????? cout<<"Date(&d)"<<endl;
??? ?}
?
private:
??? int _year;
??? int _month;
??? int _day;
};
void FunTest()
{
??? Date d;
??? Date d1(d);
}
運(yùn)行結(jié)果:
?????? 系統(tǒng)默認(rèn)合成拷貝構(gòu)造函數(shù):在A類(lèi)有缺省的構(gòu)造函數(shù),B類(lèi)沒(méi)有顯示的定義拷貝構(gòu)造函數(shù),B類(lèi)中含有A類(lèi)類(lèi)型成員,此時(shí)系統(tǒng)默認(rèn)合成拷貝構(gòu)造函數(shù)。
class Time
{
public:
?
??? Time()
??? {
?????? cout<<"Time(int intint )"<<endl;
??? }
private:
??? int _hour;
??? int _minute;
??? int _second;
};
class Date
{
public:
??? ?Date(int year = 1, int month = 2, int day = 3)
?????? :_year(year),
?????? _month(month),
?????? _day(day)
?????? {
?????????? cout<<"Date(int, int,int)"<<endl;
?????? }
?
private:
??? int _year;
??? int _month;
??? int _day;
??? Time t;
};
void FunTest()
{
??? Date d;
??? Date d1(d);
}
運(yùn)行結(jié)果:
?
3、? 析構(gòu)函數(shù):與構(gòu)造函數(shù)功能相反,在對(duì)象被銷(xiāo)毀時(shí),由編譯器自動(dòng)調(diào)用,完成類(lèi)的一些資源清理和汕尾工作
?
析構(gòu)函數(shù)特性:
a、析構(gòu)函數(shù)在類(lèi)名(即構(gòu)造函數(shù)名)加上字符~。
b、析構(gòu)函數(shù)無(wú)參數(shù)無(wú)返回值。
c、一個(gè)類(lèi)有且只有一個(gè)析構(gòu)函數(shù)。若未顯示定義,系統(tǒng)會(huì)自動(dòng)生成缺省的析構(gòu)函數(shù)。
d、對(duì)象生命周期結(jié)束時(shí),C++編譯系統(tǒng)系統(tǒng)自動(dòng)調(diào)用析構(gòu)函數(shù)。
e、注意析構(gòu)函數(shù)體內(nèi)并不是刪除對(duì)象,而是做一些清理工作
?
class Date
{
public:
??? Date(int year, int month, int day)
?????? : _year(year)
?????? , _month(month)
?????? , _day(day)
??? {
?????? cout<<"Date(int, int,int):"<<this<<endl;
??? }
?
??? Date(const Date& d)
?????? : _year(d._year)
?????? , _month(d._month)
?????? , _day(d._day)
??? {
?????? cout<<"Date(constDate& d):"<<this<<endl;
??? }
?
??? Date& operator=(const Date& d)
??? {
?????? cout<<"Date&operator=(const Date& d):"<<this<<endl;
?????? if (this != &d)
?????? {
?????????? _year = d._year;
?????????? _month = d._month;
?????????? _day = d._day;
?????? }
?
?????? return *this;
??? }
?
??? ~Date()
??? {
?????? cout<<"~Date():"<<this<<endl;
??? }
?
private:
??? int _year;
??? int _month;
??? int _day;
};
?
void FunTest()
{
??? Date d(2016, 10, 17);
??? Date d1(d);
}
運(yùn)行結(jié)果:
析構(gòu)函數(shù)銷(xiāo)毀對(duì)象原則:先構(gòu)造后析構(gòu),后構(gòu)造先析構(gòu)。
?
賦值運(yùn)算符重載:
?
????? 在面向?qū)ο蟪绦蛟O(shè)計(jì)中,對(duì)象間的相互拷貝和賦值是經(jīng)常進(jìn)行的操作,如果對(duì)象在申明的同時(shí)馬上進(jìn)行的初始化操作,則稱之為拷貝運(yùn)算。例如:
???????class?A(“Date”) ;? class B = A;
?????此時(shí)其實(shí)際調(diào)用的是B(A)這樣的淺拷貝操作。
????如果對(duì)象在申明之后,在進(jìn)行的賦值運(yùn)算,我們稱之為賦值運(yùn)算。例如:
????????class? A("Date");? class B;
????????B=A;
????????此時(shí)實(shí)際調(diào)用的類(lèi)的缺省賦值函數(shù)B.operator=(A);
?
class Date
{
public:
??? Date(int year = 2016, int month = 10 , int day = 1)
?????? : _year(year)
?????? , _month(month)
?????? , _day(day)
??? {
?????? cout<<"Date(int, int,int):"<<this<<endl;
??? }
?
??? Date(const Date& d)
?????? : _year(d._year)
?????? , _month(d._month)
?????? , _day(d._day)
??? {
?????? cout<<"Date(constDate& d):"<<this<<endl;
??? }
?
??? Date& operator=(const Date& d)
??? {
?????? cout<<"Date&operator=(const Date& d):"<<this<<endl;
?????? if (this != &d)
?????? {
?????????? _year = d._year;
?????????? _month = d._month;
?????????? _day = d._day;
?????? }
?????? return *this;
??? }
?
??? ~Date()
??? {
?????? cout<<"~Date():"<<this<<endl;
??? }
?
private:
??? int _year;
??? int _month;
??? int _day;
};
void FunTest()
{
??? Date d(2016, 10, 17);
Date d1(d); // 調(diào)用拷貝構(gòu)造函數(shù)進(jìn)行拷貝
Date d2;
??? D2 = d;????//d1.operator(&d)賦值運(yùn)算符重載
}
程序編譯之后,d1 和 d2 在棧上都分配了內(nèi)存,,對(duì)象d1 的域被初始化,d2為隨機(jī)值。
如果我們簡(jiǎn)單的執(zhí)行Date d1(d); 即 Date d1 = d; 則其執(zhí)行的是缺省定義的缺省的賦值運(yùn)算。所謂缺省的賦值運(yùn)算,是指對(duì)象中的所有位于stack中的域,進(jìn)行相應(yīng)的復(fù)制。但是,如果對(duì)象有位于heap上的域的話,其不會(huì)為拷貝對(duì)象分配heap上的空間,而只是指向相同的heap上的同一個(gè)地址。
因此,對(duì)于缺省的賦值運(yùn)算,如果對(duì)象域內(nèi)沒(méi)有heap上的空間,其不會(huì)產(chǎn)生任何問(wèn)題。但是,如果對(duì)象域內(nèi)需要申請(qǐng)heap上的空間,那么在析構(gòu)對(duì)象的時(shí)候,就會(huì)連續(xù)兩次釋放heap上的同一塊內(nèi)存區(qū)域,從而導(dǎo)致異常。
?
故需要用賦值運(yùn)算符重載
?
Date d2;
??? D2 = d;????//d1.operator(&d)賦值運(yùn)算符重載
?
? Date& operator=(const Date& d)
??? {
?????? cout<<"Date&operator=(const Date& d):"<<this<<endl;
??? ??? if (this != &d)
?????? {
?????????? _year = d._year;
?????????? _month = d._month;
?????????? _day = d._day;
?????? }
?????? return *this;
? }//一定要返回引用,否則返回其值后立即消失,不能連續(xù)賦值
?
總結(jié)
- 上一篇: java打印的globa类l_Sprin
- 下一篇: 【无标题】计算机一级考试MS OFFIC