C++(四)類和對象-默認的成員函數

隱含的this指針

1.每個成員函數都有一個指針形參,它的名字是固定的,稱爲this指針,this指針是隱式的。
2.編譯器會對成員函數進行處理,在對象調用成員函數的時候,對象地址作爲實參傳遞給成員函數的第一個形參this指針。
3.this指針是成員函數隱含指針形參,是編譯器自己處理的,我們不能在成員函數的形參中添加this的參數定義,也不能在調用時,顯示傳遞對象的地址給this指針。

類的默認成員函數
這裏寫圖片描述

我們定義一個日期類作爲例子

class Date
{
public:
    void Display()
    {
        cout<<_year<<"-"<<_month<<"-"<<_day<<endl;
    }
    private:
        int _year;
        int _month;
        int _day;
};

日期的成員變量是私有的,我們怎麼初始化這些私有的成員變量?

1.構造函數

成員變量爲私有的,要對他們進行初始化,必須用一個共有函數來進行,同時這個函數應該有且僅在定義對象時自動執行一次,這時調用的函數稱爲構造函數。

構造函數是特殊的成員函數,它的特徵:
1.函數名與類名相同。
2.無返回值。
3.對象構造時系統自動調用對應的構造函數。
4.構造函數可以重載。
5.構造函數可以在類中定義,也可以在類外定義。
6.如果類定義中沒有給出析構函數,則C++編譯器自動產生一個缺省的構造函數,但只要我們定義了一個構造函數,系統就不會自動生成缺省的構造函數。
7.無參的構造函數和全缺省的構造函數,都認爲是缺省構造函數,並且缺省構造函數只能有一個

無參構造函數&帶參構造函數
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 TestDate1()
{
    Date d1;
    Date d2(2015,1,1);
}

帶缺省參數的構造函數

Date(int year = 2000,int month = 1;int day = 1)
{
    -year = year;
    _month = month;
    _day = day;
}

拷貝構造函數

創建對象時使用同類對象來進行初始化,這時所用的構造函數稱爲拷貝構造函數,拷貝構造函數是特殊的構造函數。

特徵:
1.拷貝構造函數其實是構造函數的重載。
2.拷貝構造函數的形參必須使用引用傳參,使用傳值方式會引起無限遞歸調用。
3.若未顯示定義,系統會默認缺省的拷貝構造函數。缺省的拷貝構造函數會依次拷貝類成員進行初始化、

class Date
{
public:
    Date()
    {}
    //拷貝構造函數
    Date(const Date& d)
    {
        _year = d._year;
        _month = d._month;
        _day = d._day;
    }//在這裏我們對象可以直接訪問私有的成員變量
    //1.在類的成員函數中可以直接訪問同類對象的私有/保護成員
    //2.C++的訪問限定符是以類爲單位的,也就是說在這個單位內的成員可以互相訪問。
private:
    int _year;
    int _month;
    int _day;
};
void TestDate1()
{
    Date d1;
    //下面兩種用法都是調用拷貝構造函數,是等價的。
    Date d2(d1);
    Date d3 = d1;
}

析構函數

當一個對象的生命週期結束時,C++編譯系統會自動調用一個成員函數,這個特殊的成員函數就是析構函數。
析構函數是特殊的成員函數特徵如下:
1.析構函數在類名上加字符~。
2.析構函數無參數返回值。
3.一個類有且只有一個析構函數。若未顯示定義,系統會自動生成缺省的析構函數。
4.對象生命週期結束時,C++編譯系統自動調用析構函數。
5.注意析構函數體內並不是刪除對象,而是做了一些清理工作。

賦值運算符重載

拷貝構造函數是創建的對象,使用一個已有對象來初始化這個準備創建的對象。
賦值運算符的重載是對一個已經存在的對象進行拷貝賦值

class Date
{
public:
    Date()
    {}
    //拷貝構造函數
    Date(const Date& d)
        :_year(d._year)
        ,_month(d._month)
        ,_day(d._day)
    {}

    //賦值操作符的重載
    Date& operator=(const Date& d)
    {
        if(this != &d)//判斷是不是本身
        {
            this->_year = d._year;
            this->_month = d._month;
            this->_day = d._day;
        }
        return *this;
        //我們的this 被賦值了,而且出了函數還存在,那麼就要拿Date類型來接收參數
    }
private:
    int _year;
    int _month;
    int _day;
};
void Test()
{
    Date d1;
    Date d2 = d1;//調用拷貝函數
    Date d3;
    d3 = d1;//調用賦值運算符的重載
}

深入探索構造函數

類的成員變量有兩種初始化方式:
1.初始化列表。
2.構造函數體內進行復制。

初始化列表以一個冒號開始,接着一個都要分隔數據列表,每個數據成員都放在一個括號中進行初始化。儘量使用初始化列表進行初始化,因爲它更高效。

哪些成員變量必須放在初始化列表裏面?
1.常量成員變量。
2.引用類型成員變量。
3.沒有缺省構造函數的類成員變量。

成員變量按聲明順序依次初始化,而費初始化列表出現的順序

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章