c++---類的默認成員函數

類的默認成員函數

類的組成包括數據成員與成員函數。

在類中一共有有六個默認成員函數,

  1. 構造函數
  2. 拷貝構造函數
  3. 析構函數
  4. 賦值操作符重載
  5. 取地址操作符重載
  6. const修飾的取地址操作符重載

利用一個實例(日期類)進行舉例
先是定義一個日期類

class Date
{
  public:
    void show(); 
  private:
    int _year;
    int _month;
    int _day;
};

這就是一個簡單的類定義。下面依次介紹各個默認成員函數

一.構造函數

因爲在類中,數據是私有的,只能在類內進行訪問操作,所以初始化這些數據也就只能在類進行,需要定義一個公有函數,這就是構造函數。這個函數只有在定義對象時對其初始化使用一次。

Date();
  1. 構造函數的函數沒有返回值。
  2. 構造函數的名字一定是與類名相同的。
  3. 構造函數可以重載,可以是有參的,無參的
  4. 在進行類的實例化的時候,就會自動調用構造函數,若是沒有定義就會調用系統自動生成的構造函數,若是有人爲定義,則會根據其參數進行選擇對應的構造函數及其重載函數。
  5. 構造函數可以其他成員函數相同,也可以在類外進行定義,在類內聲明。
  6. 無參的構造函數與全缺省的構造函數都認爲是缺省構造函數,並且缺省的構造函數只能有一個
//無參的構造函數
Date()
{
    _year=1900;
    _month=1;
    _day=1;
}
//全缺省的構造函數
Date(int year=1900, int month=1, int month=1)
{
    _year=year;
    _month=month;
    _day=day;
}

int main()
{
    Date d1;
    //Date d2;
}

由於上述兩種函數的調用方式相同,都是不需要傳參的,所以如果一個類中既有無參的構造函數又有全缺省的構造函數,就會出現錯誤,不知道當前應該調用哪個構造函數來進行初始化。所以在類的定義中不可以同時出現這兩種構造函數。

二.拷貝構造函數

拷貝構造函數是創建隊形在初始化時用同類的對象進行初始化。也是一種構造函數。

//拷貝構造函數:
Date(const Date& d)
{
    _year=d._year;
    _month=d._month;
    _day=d._day;
}
int main()
{
    Date d1(2018,3,20);
    Date d2(d1);
    Date d3=d2;   // 這樣也算是拷貝構造函數 
}
  1. 拷貝構造函數是構造函數的重載
  2. 拷貝構造函數的參數必須使用引用傳參,若使用傳值傳參則會引起無限的遞歸調用。在調用這個函數時,會傳進來一個實參,形參用於接收,所以在這個函數的棧幀中會形成一個臨時變量,用於儲存實參的值,這裏的這個空間需要用拷貝構造函數初始化,所以此時就需要遞歸調用拷貝構造函數,調用拷貝函數又會需要形成臨時變量,所以就會一直遞歸調用,就無法出來。造成了無窮遞歸的現象。
  3. 若在類中沒有定義,則系統會默認缺省的拷貝構造函數,就會依次拷貝類成員進行初始化。

三.析構函數

當一個對象的生命週期結束時,c++編譯系統會自動調用一個成員函數,就是析構函數。
1. 析構函數的函數名是在類名前加~
2. 析構函數沒有參數也沒有返回值
3. 一個類中就只有一個析構函數,不支持重載,若沒有定義,則系統會默認生成。
4. 析構函數的作用是清理空間,若在創建對象時,有malloc出來的空間,將他們銷燬。析構函數並不是刪除對象,對象是在生命週期結束後會有操作系統將其收回。不需要人爲收回。

class Test
{
    pubilc:
      Test(int size)
      {
          ptr=(int *)malloc(size * sizeof(int))
      }
      ~Test()
      {
          if(ptr)
          {
              free(ptr);
              ptr=0;
          }
      }
    private:
      int *ptr;
}

析構函數的調用順序與構造函數相反。先定義的函數先調用其構造函數,後調用析構函數。

四.運算符重載

運算符重載是爲了增加程序的可讀性。因爲沒有經過重載的運算符是不能運算自定義類型的,例如日期的加減,就不能單純的只用未重載的運算符進行計算。需要根據不同情況自己定義。

運算符重載的特徵:

operator+運算符 構成函數名

重載運算符以後,不能改變運算符的優先級/結合性/操作數個數

//運算符小於的重載
bool operator<(const Date& d)
{
    //自定義函數內部。
}

c++中不可以重載的運算符
1. .*
2. sizof
3. ::
4. ? :
5. .

賦值運算符的重載

首先需要說明一下賦值運算符與拷貝構造函數的區別

  拷貝構造函數是在創建對象時使用的,用一個已有對象初始化這個剛創建的對象。而賦值是給一個已經創建好的對象進行拷貝賦值。

函數名是operator+運算符,爲了可讀性更高,編譯系統會在碰見重載的運算符時,檢查運算符的操作數是否爲自定義類型,若是自定義類型,就轉到運算符重載函數。進行函數內部操作。

bool operator=(const Date& d)
{
    return _year=d._year;
        && _month=d._month;
        && _day=d._day;
}

在這裏是只需要傳一個參數。還有一個是隱含的this指針,所以上述代碼就可以等價於

bool operator=(Date *thisconst Date& d)
{
    return this->_year=d._year;
        && this->_month=d._month;
        && this->_day=d._day;
}
發佈了65 篇原創文章 · 獲贊 31 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章