類和對象1--四個默認成員函數+運算符重載

類的聲明和定義
C++中的類的定義一般分爲類的聲明和類的實現部分。類的聲明部分用來說明該類的成員(數據成員、成員函數),告訴使用者“幹什麼”。類的實現部分用來定義成員函數,該函數用來對數據成員進行操作,告訴使用者“怎麼幹”。

class<類名>
{
   public:
   <成員函數或數據成員的說明>
   protected:
   <成員函數或數據成員的說明>
   private:
   <成員函數或數據成員的說明>
};                      //類的聲明部分
<各成員函數的實現>         //類的實現部分

例如,我們可以定義一個簡單的學生類:

class Student        //Student爲類名
{
    public//訪問限定符
    void Display() //成員函數
    {}
    privatechar name[10];    //成員變量
    int num;
    char sex;
};

C++的三大特性:封裝、繼承、多態。
函數是封裝的一種形式:函數所執行的細節行爲被封裝在函數本身這個更大的實體中,被封裝的元素隱藏了他們的實現細節—可以調用一個函數但是不能夠訪問函數所執行的語句。
封裝:隱藏對象的屬性和實現細節,僅對外公開接口和對象進行交互,將數據和操作數據的方法進行有機結合。
類成員有以下3種不同的訪問限定符
(1)公有成員訪問限定符(public):既可以被本類中的成員函數訪問,也可以被類的作用域內的其他函數訪問。
(2)私有成員訪問限定符(private):成員只能被該類中的成員函數訪問,類外的其他函數則不能(友元類除外)
(3)保護成員訪問限定符(protected):成員只能被該類的成員函數或派生類的成員函數訪問。
【說明】
1、public成員在類外可以直接訪問
2、protected和private成員在類外(在此可將protected和private理解成private)不能夠訪問。
3、它們的作用域從該訪問限定符出現的位置開始直到下一個訪問限定符出現時爲止。
4、class的默認訪問權限是private,而struct爲public型(因爲struct要兼容C)。
5、如果在類的定義中既不指定private,也不指定public,則系統默認是私有的。

class Date
{
  public:
  void SetDate(int year=2017, int month = 6, int day = 24)
  {
   _year = year;
   _month = month;
   _day = day;
  }
  void PrintDate()
  {
   cout<<_year<< "-"<<_month<<"-" <<_day<<endl;
  }
  private:
  int _year;
  int _month;
  public:
  int _day;
};
int main()
{
   Date d;
   d.SetDate(2017, 6, 25);
   d.PrintDate();
   // d._year = 2017; // 私有成員變量不能再類外直接訪問
   // d._month = 6;
      d._day = 25;
   return 0;
}

類實例化
用類類型創建對象的過程稱爲實例化。

Date d; // 類實例化

1.類只是一個模型一樣的東西,限定了類有哪些成員,定義出一個類並沒有分配實際的內存空間來存儲它。
2.一個類可以實例化出多個對象,實例化出的對象佔用實際的物理空間存儲類成員變量。
類對象存儲模型
所以每個對象的大小爲類中所有成員變量的大小之和,當然這裏也遵循內存對齊原則。
2:整理四個默認成員函數及運算符重載相關知識
構造函數
變量應該被初始化,對象也需要初始化,那麼怎麼初始化一個對象呢?
C++中定義了一種特殊的初始化函數,稱爲構造函數,當對象被創建時,構造函數自動被調用。其名字與類名相同,在對象的生命週期內只且只調用一次,以保證每個數據成員都有一個合適的初始值。
【構造函數特性】
1、函數名與類名相同。
2、沒有返回值。
3、有初始化列表(可以不用)。
4、新對象被創建,由編譯器自動調用,且在對象的生命期內僅調用一次。
5、構造函數可以重載,實參決定了調用那個構造函數。
6、如果沒有顯式定義時,編譯器會提供一個默認的構造函數。
7、無參構造函數和帶有缺省值得構造函數都認爲是缺省構造函數,並且缺省構造函數只能有一個。
例如:

class Date
{
  public:
  Date(int year=2017, int month = 6, int day = 24) //全缺省的構造函數,不能和無參的構造函數Date(){}同時存在,因爲兩個都可以不傳參調用
  {
   _year = year;
   _month = month;
   _day = day;
  }

  private:
  int _year;
  int _month;
  int _day;
};

【默認構造函數】
類如果沒有顯式定義構造函數時,編譯器會合成一個默認的構造函數,該構造函數中什麼工作都不做。只要顯式定義了,即使該構造函數什麼也不做,編譯器也不會爲該類合成默認的構造函數。編譯器生成的默認構造函數使用與成員變量初始化相同的規則來初始化成員,具有類類型的成員通過運行各自的默認構造函數來進行初始化。內置和複合類型的成員如指針、數組,只對定義在全局作用域中的對象初始化,當對象定義在局部作用域時,內置和符合類型的成員不進行初始化。在某些情況下,默認構造函數是由編譯器隱式使用的。

拷貝構造函數
只有單個形參,而且該形參是對本類類型對象的引用(常用const修飾),這樣的構造函數稱爲拷貝構造函數。拷貝構造函數是特殊的構造函數,創建對象時使用已存在的同類對象來進行初始化,由編譯器自動調用。

class Date
{
  public:
  Date()
  {
  }
  Date(int year, int month, int day) 
  {
   _year = year;
   _month = month;
   _day = day;
  }
  Date(const Date& date)
 {
   _year = date._year;
   _month = date._month;
   _day = date._day;
  }
  private:
  int _year;
  int _month;
  int _day;
};

【特徵】
1、它是構造函數的重載。
2、它的參數必須使用同類型對象的引用傳遞。
3、如果沒有顯式定義,系統會自動合成一個默認的拷貝構
造函數。默認的拷貝構造函數會依次拷貝類的數據成員完成初始化。
【使用場景】
1、對象實例化對象

Date d1(2017, 6, 25);
Date d2(d1);

2、傳值方式作爲函數的參數

void FunTest(const Date date)
{}

3、傳值方式作爲函數返回值

Date FunTest()
{
   Date date;
   return date;
}

析構函數
析構函數:與構造函數功能相反,在對象被銷燬時,由編譯器自動調用,完成類的一些清理工作。例如,在建立對象是用new分配的內存空間,應在析構函數中用delete釋放。析構函數也與類同名,但在名字前面有一個“~”符號,析構函數沒有返回值和返回類型。

class Array
{
   public:
   Array(size_t capacity)
   : _capacity(capacity)
  {
    _pData = ( int*)malloc(capacity*sizeof (int));
    _size = 0;
  }
   ~Array()
  {
    if (NULL != _pData)
    {
     free(_pData);
     _pData = NULL; 
    }
    _size = 0;
    _capacity = 0;
  }
  private:
  int* _pData;
  size_t _size;
  size_t _capacity;
};

【特性】
a、析構函數在類名(即構造函數名)加上字符~。
b、析構函數無參數無返回值。
c、一個類有且只有一個析構函數。若未顯示定義,系統會
自動生成缺省的析構函數。
d、對象生命週期結束時,C++編譯系統系統自動調用析構函
數。
e、注意析構函數體內並不是刪除對象,而是做一些清理工
作。
運算符重載
在C++中可以用關鍵字operator加上運算符來表示一個函數,即運算符重載。下面兩個複數相加的函數爲例進行介紹。假定定義了複數類Complex,則有:

Complex Addition(Complex a,Complex b);

可以用運算符重載來表示

Complex operator+(Complex a,Complex b);

這樣就可以寫成a+b的形式了。
然而並非所有的運算符都可以重載,下面是不能重載的運算符函數:
這裏寫圖片描述
注意:
1、不能通過連接其他符號來創建新的操作符:比如

operator@;
void operator @(){}

2、重載操作符必須有一個類類型或者枚舉類型的操作數

int operator +(const int _iNum1 , const int _iNum2 )
// 報錯
{
return ( _iNum1 + _iNum2);
}
typedef enum TEST {one ,two ,three };
int operator+(const int _iNum1 , const TEST _test )
{
return _iNum1;
}

3、用於內置類型的操作符,其含義不能改變,例如:內置的整型+,不能改變其含義
5、不再具備短求職特性重載操作符不能保證操作符的求值順序,在重載&&和||中,對每個操作數都要進行求值,而且對操作數的求職順序不能做規定,因此:重載&&、||和逗號操作符不是好的做法。
6、作爲類成員的重載函數,其形參看起來比操作數數目少1成員函數的操作符有一個默認的形參this,限定爲第一個形參。

CTest operator+(const CTest test1, const CTest test2)const // 報錯
{
return test1;
}
CTest operator+(const CTest test1)const
{
return test1;
}

7、一般將算術操作符定義爲非成員函數,將賦值運算符定義成員函數
8、操作符定義爲非類的成員函數時,一般將其定義爲類的友元
9、== 和 != 操作符一般要成對重載
10、下標操作符[]:一個非const成員並返回引用,一個是const成員並返回引用
11、解引用操作符*和->操作符,不顯示任何參數
13、自增自減操作符
前置式++/–必須返回被增量或者減量的引用
後綴式操作符必須返回舊值,並且應該是值返回而不是引用
返回
14、輸入操作符>>和輸出操作符<<必須定義爲類的友元函數

3.隱含的this指針
http://blog.csdn.net/rae8023/article/

發佈了49 篇原創文章 · 獲贊 28 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章