PKU C++程式設計實習 學習筆記4 運算子多載

來源:互聯網
上載者:User

標籤:c++   操作符   運算子   重載   

第四章 運算子多載

4.1 運算子多載的基本概念1. 運算子2. 自訂資料類型與運算子多載

C++提供了資料抽象的手段:使用者自己定義資料類型 -- 類
? 調用類的成員函數—>操作它的對象

類的成員函數—>操作對象時,很不方便
? 在數學上,兩個複數可以直接進行+/-等運算 Vs. 在C++中,直接將+或-用於複數是不允許的

3. 運算子多載
  • 對抽象資料類型也能夠直接使用C++提供的運算子
            ? 程式更簡潔
            ? 代碼更容易理解
  • 運算子多載
            ? 對已有的運算子賦予多重的含義
            ? 使同一運算子作用於不同類型的資料時—>不同類型的行為
  • 目的
            ? 擴充C++中提供的運算子的適用範圍,以用於類所表示的抽象資料類型
  • 同一個運算子,對不同類型的運算元,所發生的行為不同
            ? (5,10i) + (4,8i) = (9,18i)
            ? 5 + 4 = 9
  • 運算子多載的實質是函數重載
    返回值類型 operator 運算子(形參表)
    {
    ……
    }
  • 在程式編譯時間:
            ? 把含 運算子的運算式  —> 對 運算子函數 的調用
            ? 把 運算子的運算元 —> 運算子函數的 參數
            ? 運算子被多次重載時, 根據 實參的類型 決定調用哪個運算子函數
            ? 運算子可以被重載成普通函數
            ? 也可以被重載成類的成員函數
4. 運算子多載為普通函數
class Complex {  public:    Complex( double r = 0.0, double i= 0.0 ){      real = r;      imaginary = i;    }  double real; // real part  double imaginary; // imaginary part};Complex operator+ (const Complex & a, const Complex & b){  return Complex( a.real+b.real, a.imaginary+b.imaginary);} // “類名(參數表)” 就代表一個對象Complex a(1,2), b(2,3), c;c = a + b;// 相當於什麼?  operator+(a,b)
重載為普通函數時,參數個數為運算子目數
5. 運算子多載為成員函數
class Complex {  public:    Complex( double r= 0.0, double m = 0.0 ):real(r), imaginary(m) { } // constructor    Complex operator+ ( const Complex & ); // addition    Complex operator- ( const Complex & ); // subtraction  private:    double real; // real part    double imaginary; // imaginary part};// Overloaded addition operatorComplex Complex::operator+(const Complex & operand2) {  return Complex( real + operand2.real,imaginary + operand2.imaginary );}// Overloaded subtraction operatorComplex Complex::operator- (const Complex & operand2){  return Complex( real - operand2.real,imaginary - operand2.imaginary );}int main(){ Complex x, y(4.3, 8.2), z(3.3, 1.1); x = y + z;// 相當於什麼?  y.operator+(z) x = y - z;// 相當於什麼?  y.operator-(z) return 0;}
重載為成員函數時,參數個數為運算子目數減一
4.2 賦值運算子的重載1. 賦值運算子 ‘=’ 重載賦值運算子 兩邊的類型 可以 不匹配
? 把一個 int類型變數 賦值給一個 Complex對象
? 把一個 char * 類型的字串 賦值給一個 字串對象

需要 重載賦值運算子 ‘=’

賦值運算子 “=” 只能重載為 成員函數

編寫一個長度可變的字串類String
? 包含一個char * 類型的成員變數
—> 指向動態分配的儲存空間
? 該儲存空間用於存放 ‘\0’ 結尾的字串

class String {  private:    char * str;  public:    String () : str(NULL) { } //建構函式, 初始化str為NULL    const char * c_str() { return str; } //傳回值為const類型,保證str不會被修改。比如char* p=str.c_str();則編譯器會報錯,類型不符。    char * operator = (const char * s);    ~String( );//需要考慮String對象是否指向了動態分配的儲存空間}; //重載‘=’使得obj = “hello”能夠成立char * String::operator = (const char * s){  if(str) delete [] str;  if(s) { //s不為NULL才會執行拷貝    str = new char[strlen(s)+1];    strcpy(str, s);  }  else    str = NULL;  return str;}String::~String( ) {  if(str) delete [] str;};int main(){  String s;  s = “Good Luck,” ;  cout << s.c_str() << endl;  // String s2 = “hello!”; //這條語句要是不注釋掉就會出錯  s = "Shenzhou 8!";  cout << s.c_str() << endl;  return 0;}
2. 重載賦值運算子的意義 – 淺複製和深複製

S1 = S2;

  • 淺複製/淺拷貝
            執行逐個位元組的複製工作




S1和S2指向了同一塊動態分配記憶體地區,那麼當S1和S2同時消亡的時候,這一塊記憶體空間就會被先後釋放兩次。這樣就會導致嚴重的記憶體錯誤,甚至可能引發程式意外的中止。
所以我們看到,這樣的一個淺拷貝,或者淺複製的工作本身並不能實現我們所希望實現的像S2中間的這個str字串複製給S1本身指向的那一塊空間。

  • 深複製/深拷貝
            將一個對象中指標變數指向的內容 —> 複製到另一個對象中指標成員對象指向的地方



在 class MyString 裡新增成員函數:

String & operator = (const String & s) {  if(str) delete [] str;  str = new char[strlen(s.str)+1];  strcpy(str, s.str);  return * this;}

3. 思考

考慮下面語句,是否會有問題?
MyString s;    s = “Hello”;    s = s;

正確寫法:

String & String::operator = (const String & s){  if(str == s.str) return * this;//增加此行  if(str) delete [] str;  if(s.str) { //s.str不為NULL才會執行拷貝    str = new char[strlen(s.str)+1];    strcpy( str,s.str);  }  else    str = NULL;  return * this;}

4. 對 operator = 返回值類型的討論
  • void 好不好?
            考慮: a = b = c;
            //等價於a.operator=(b.operator=(c));
  • String 好不好?為什麼是 String &
            運算子多載時, 好的風格 -- 盡量保留運算子原本的特性
            考慮: (a=b)=c; //會修改a的值
            分別等價於:(a.operator=(b)).operator=(c);

5. 上面的String類是否就沒有問題了?

為 String類編寫 複製建構函式 時,會面臨和 ‘=’ 同樣的問題,用同樣的方法處理

String::String(String & s){  if(s.str) {    str = new char[strlen(s.str)+1];    strcpy(str, s.str);  }  else    str = NULL;}

4.3 運算子多載為友元函數1. 運算子多載為友元
  • 通常,將運算子多載為類的成員函數
  • 重載為友元函數的情況:
            ? 成員函數不能滿足使用要求
            ? 普通函數,又不能訪問類的私人成員
class Complex{    double real, imag;  public:    Complex(double r, double i):real(r), imag(i){ };    Complex operator+(double r);};Complex Complex::operator+(double r){ //能解釋 c+5  return Complex(real + r, imag);}
經過上述重載後:
Complex c ;
c = c + 5; //有定義,相當於 c = c.operator +(5);
但是:
c = 5 + c; //編譯出錯
為了使得上述運算式能成立, 需要將+重載為普通函數
Complex operator+ (double r, const Complex & c) {  //能解釋 5+c  return Complex( c.real + r, c.imag);}
普通函數不能訪問私人成員 —> 將運算子+重載為友元函數
class Complex {    double real, imag;  public:    Complex( double r, double i):real(r),imag(i){ };    Complex operator+( double r );    friend Complex operator + (double r, const Complex & c);};

PKU C++程式設計實習 學習筆記4 運算子多載

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.