閱讀44 返回首頁    go 阿裏雲 go 技術社區[雲棲]


玩轉C++運算符重載

運算符重載語法:返回值類型  operator運算符(參數列表) {  代碼邏輯。。。 }

C++中的運算符重載是通過函數來實現的,可以將重載的運算符看作是類成的一個成員函數,向普通函數一樣調用。如重載String類的 + 運算符,調用的時候可以這樣:

class {
   // .....
   String operator+(const String &str)
   { .... }
}

String str1 = "hello ";
String str2 = "cplusplus";
String str3 = str1.operator+(str2);
        從上述代碼中可以看出,operator+就像是String類的一個函數,可以像普通函數一樣調用,將要相加的字符串對象作為實參傳遞給函數即可。所以從這可以得出一個函數重載的步聚:(以上述+重載為例)

1、寫出運算符的函數原型

str1.operator+(str2); 

從這可以得知,+ 需要兩個操作數,str1和str2(即兩個字符串對象),返回值類型為String對象(加法運算後的結果)。由於是作為類的成員函數重載,所以str1在進行 + 運算時作為this指針傳給函數,函數隻需要一個參數即可,即被相加的字符串對象str2。

2、寫出函數聲明

從函數原型可以得出函數聲明:String operator+(const String &str);

3、實現函數細節

String String::operator+(const String &str)
{
    if (str.buff == nullptr)
    {
        return *this;
    }
    
    size_t totallen = str.len + this->len + 1;
    char *buff = new char[totallen];
    
    strcpy(buff, this->buff);
    strcat(buff, str.buff);
    
    String temp(buff);
    return temp;
}

下麵這個示例重載了字符串操作的常用操作符:

//
//  String.h
//  C++運算符重載
//
//  Created by 楊信 on 14-5-8.
//  Copyright (c) 2014年 yangxin. All rights reserved.
//

#ifndef __C______String__
#define __C______String__

#include <iostream>

using namespace std;

class String
{
private:
    char *buff;
    size_t len;
    
public:
    String();
    
    // 用一個字符串初始化對象
    String(const char *buff);
    
    // 拷貝構造
    String(const String &str);
    
    // 析構
    ~String();
    
    // 設置字符串內容
    void setString(const char *buff);
    
    // 獲取字符串的長度
    size_t length() const;
    
    // 獲取字符串內容
    char * getStr() const;
    
    // 比較兩個字符串是否相等
    bool operator==(String &str);
    
    // 比較兩個字符串是否不相等
    bool operator!=(String &str);
    
    // 比較兩個字符串的大小
    bool operator>(String &str);
    
    // 比較兩個字符串的大小
    bool operator<(String &str);
    
    // 獲取或修改字符串中的某一個字符
    char& operator[](int index);
    
    // 賦值構造函數
    String& operator=(const String &str);
    
    // 兩個字符串相加
    String operator+(const String &str);
    
    // 字符串累加
    String& operator+=(const String &str);
    
    // 從輸入流中獲取字符串
    friend istream& operator>>(istream &input, String &str);
    
    // 將字符串輸出到輸出流
    friend ostream& operator<<(ostream &output, const String &str);
    
};

#endif /* defined(__C______String__) */

//
//  String.cpp
//  C++運算符重載
//
//  Created by 楊信 on 14-5-8.
//  Copyright (c) 2014年 yangxin. All rights reserved.
//

#include "String.h"
#include <string>
#include <cassert>
#include <cmath>

String::String()
{
    this->buff = nullptr;
    this->len = 0;
}

// 用一個字符串初始化對象
String::String(const char *buff):buff(nullptr), len(0)
{
    setString(buff);
}

// 拷貝構造
String::String(const String &str)
{
    setString(str.buff);
}

// 析構
String::~String()
{
    // 釋放內存
    if (this->buff != nullptr)
    {
        delete[] buff;
        buff = nullptr;
        len = 0;
    }
}

void String::setString(const char *buff)
{
    if (buff == nullptr)
    {
        return;
    }
    
    if (this->buff != nullptr) {
        delete[] this->buff;
        this->buff = nullptr;
        this->len = 0;
    }
    
    size_t len = strlen(buff);
    this->buff = new char[len + 1];
    this->len = len;
    strcpy(this->buff, buff);
}

// 獲取字符串的長度
size_t String::length() const
{
    return this->len;
}

// 獲取字符串內容
char * String::getStr() const
{
    return this->buff;
}

// 獲取或修改字符串中的某一個字符
char& String::operator[](int index)
{
    assert(index < this->len);
    
    return this->buff[index];
}

// 比較兩個字符串是否相等
bool String::operator==(String &str)
{
    if (this->len != str.len)
    {
        return false;
    }
    
    for (int i = 0; i < this->len; ++i)
    {
        if (this->buff[i] != str[i])
        {
            return false;
        }
    }
    
    return true;
}

// 比較兩個字符串是否不相等
bool String::operator!=(String &str)
{
    return !(*this == str);
}

// 比較兩個字符串的大小
bool String::operator>(String &str)
{
    char *pstr = this->buff;
    char *pstr2 = str.buff;
    while (*pstr != '\0' && *pstr2 != '\0')
    {
        if (*pstr > *pstr2) {
            return true;
        }
        pstr++;
        pstr2++;
    }
    return false;
}

// 比較兩個字符串的大小
bool String::operator<(String &str)
{
    return !(*this > str);
}

// 賦值構造函數
String& String::operator=(const String &str)
{
    setString(str.buff);
    
    return *this;
}

// 兩個字符串相加
String String::operator+(const String &str)
{
    if (str.buff == nullptr)
    {
        return *this;
    }
    
    size_t totallen = str.len + this->len + 1;
    char *buff = new char[totallen];
    
    strcpy(buff, this->buff);
    strcat(buff, str.buff);
    
    String temp(buff);
    return temp;
}

// 字符串累加
String& String::operator+=(const String &str)
{
    if (str.buff == nullptr)
    {
        return *this;
    }
    
    // 創建一個臨時緩衝區,存儲對象本身的字符串和相加的字符串
    size_t len = this->len + str.length();
    char *temp = new char[len + 1];
    strcpy(temp, this->buff);
    strcat(temp, str.buff);
    
    // 設置新的字符串給對象本身
    setString(temp);
    
    return *this;
}

// 從輸入流中獲取字符串
istream& operator>>(istream &input, String &str)
{
    // 在堆區創建臨時緩衝區,接收用戶輸入
    int size = 1024 * 10;
    char *tempbuff = new char[size];
    memset(tempbuff, 0, size);
    
    // 獲取用戶輸入
    input.getline(tempbuff, size);
    
    // 將臨時緩衝中的字符串保存到str對象的字符串緩衝區中
    str.setString(tempbuff);
    
    // 釋放臨時緩衝區數據
    delete[] tempbuff;
    tempbuff = nullptr;
    return input;
}

// 將字符串輸出到輸出流
ostream& operator<<(ostream &output, const String &str)
{
    output << str.getStr();
    return output;
}

// 測試用例
//
//  main.cpp
//  String(運算符重載)
//
//  Created by 楊信 on 14-5-8.
//  Copyright (c) 2014年 yangxin. All rights reserved.
//

#include <iostream>
#include "String.h"
#include <cmath>

using namespace std;


int main(int argc, const char * argv[])
{
   
    // 初始化
    String str1("helloz");
    String str2("helloz");
    
    // 獲取字符中內容
    cout << str1.getStr() << endl;
    
    // 獲取字符串的長度
    cout << "長度:" << str1.length() << endl;
    
    // 獲取第字符串中的第一個字符
    cout << "第1個字符:" << str1[0] << endl;
    
    // 比較兩個字符串是否相等,相等返回1,否則返回0
    bool isequal = str1 == str2;
    cout << isequal << endl;
    
    // 比較兩個字符串的大小,str1大於str2返回1,否則返回0
    cout << (str1 > str2) << endl;
    
    // 修改字符串中的第2個字符為C
    String s = "Hello";
    s[1] = 'C';
    cout << s << endl;
    
    // 測試用一個字符串去初始化另外一個字符串
    String str3 = str2;
    cout << str3.getStr() << endl;
    String str4;
    str4 = str3;
    cout << str4.getStr() << endl;
    
    // 測試兩個字符串相加
    String str5 = str1 + str2;
    cout << &str5 << endl;
    cout << str5.getStr() << endl;
    
    // 測試字符串連等
    String str6;
    String str7 = str6 = str5;
    cout << str6.getStr() << " | " << str7.getStr() << endl;
    
    // 測試字符串累加
    String str8 = "i love c++ ";
    str8 += "i love c ";
    cout << str8.getStr() << endl;
    
    // 從輸入流讀取字符串
    String str9;
    cout << "Please a string:";
    cin >> str9;
    
    // 將字符串輸出到輸出流
    cout << str9 << endl;
   
    return 0;
}
運算符重載注意事項:

  • 友元函數重載運算符時需要傳遞所有操作數
  • 成員函數重載,會將操作數本身做為this指針作為參數傳入函數,如果是多元操作符,隻需與它被操作的數傳入函數即可
  • = 號重載時,如果對象中有新分配內存的成員,要先delete,再new,如果要支持連等操作,需要返回對象本身的引用

  • 函數返回值作左值時,返回值必須為引用

  • 隻有C++預定義的操作符集中的操作符才可以被重載(不能自己隨便寫一個操作符,如:+-)
  • 重載操作符不能改變操作符的優先級,例如:先乘徐,後加減
  • 重載操作符不能改變操作數的個數

以下幾種運算符不能被重載:

  •  .    :成員選擇運算符
  • ::    :作用域運算符
  • *     : 指針運算符
  • #    :預處理標誌
  • ?:   :三目運算符,沒有確定性,重載沒有意義


最後更新:2017-04-03 12:56:35

  上一篇:go Netty4詳解二:開發第一個Netty應用程序
  下一篇:go 如何解決每次打開office2007、2010、2013都會出現正在配置