C++面向?qū)ο?運算符重載

運算符重載

運算符重載又稱為操作符重載,可以為運算符增加一些新的功能,全局函數(shù)和成員函數(shù)都支持運算符重載,我們通過具體的實例來演示下,我們聲明一個Point類,并且定義需要通過運算符重載的類。

#pragma once
#include <iostream>
using namespace std;

class Point {
    friend ostream &operator<<(ostream &, const Point &);
    int m_x;
    int m_y;
public:
    Point(int x, int y);
    // 兩個對象+ 賦值新的對象
    Point operator+(const Point &point) const;
    // 兩個對象- 賦值老的對象
    Point operator-(const Point &point) const;
    //取反
    const Point operator-() const;
    // +=
    Point &operator+=(const Point &point);
    // -=
    Point &operator-=(const Point &point);
    // 是否相等
    bool operator==(const Point &point);
    // 是否不等
    bool operator!=(const Point &point);
    // 前++
    Point &operator++();
    // 后++ 注意int為固定寫法
    const Point operator++(int);
};

Point實現(xiàn)如下:

#include "Point.h"

Point::Point(int x, int y) :m_x(x), m_y(y) { }

// 運算符(操作符)重載
Point Point::operator+(const Point &point) const {
    return Point(this->m_x + point.m_x, this->m_y + point.m_y);
}

Point Point::operator-(const Point &point) const {
    return Point(this->m_x - point.m_x, this->m_y - point.m_y);
}

const Point Point::operator-() const {
    return Point(-this->m_x, -this->m_y);
}

Point &Point::operator+=(const Point &point) {
    this->m_x += point.m_x;
    this->m_y += point.m_y;
    return *this;
}

Point &Point::operator-=(const Point &point) {
    this->m_x -= point.m_x;
    this->m_y -= point.m_y;
    return *this;
}

bool Point::operator==(const Point &point) {
    return (this->m_x == point.m_x) && (this->m_y == point.m_y);
}

bool Point::operator!=(const Point &point) {
    return (this->m_x != point.m_x) || (this->m_y != point.m_y);
}

// 前++
Point &Point::operator++() {
    this->m_x++;
    this->m_y++;
    return *this;
}

// 后++
const Point Point::operator++(int) {
    Point point(this->m_x, this->m_y);
    this->m_x++;
    this->m_y++;
    return point;
}

ostream &operator<<(ostream &cout, const Point &point) {
    return cout << "(" << point.m_x << ", " << point.m_y << ")";
}

main.cpp調(diào)用如下:

    Point p0(5, 10);
    Point p1(30, 70);
    Point p2(10, 40);
    Point p3 = p1++ - p0;
    (p1 += p2) = Point(100,300);
    Point p4 = ++p1 - p0;
    
    //以下兩個調(diào)用等價
    p1 += p2;
    p1.operator+=(p2);
    
    //以下兩個調(diào)用等價
    cout << p1;
    operator<<(cout,p1);
    

注意,運算符重載最好跟系統(tǒng)的用法靠近,比如前++和后++的重載,以及考慮到const對象等。重載cout函數(shù)不能放到成員函數(shù)實現(xiàn),因為cout在對象前,最好聲明成類的友元函數(shù),便于訪問成員變量的值。下面我們自己再維護一個String類,實現(xiàn)C++標準庫string的一些功能。

#pragma once
#include <iostream>
using namespace std;

class String {
    friend ostream &operator<<(ostream &, const String &);
public:
    String(const char *cstring = "");
    String(const String &string);
    ~String();
    String &operator=(const char *cstring);
    String &operator=(const String &string);
    String operator+(const char *cstring);
    String operator+(const String &string);
    String &operator+=(const char *cstring);
    String &operator+=(const String &string);
    bool operator>(const char *cstring);
    bool operator>(const String &string);
    char operator[](int index);
private:
    char *m_cstring = NULL;
    String &assign(const char *cstring);
    char *join(const char *cstring1, const char *cstring2);
};



#include "String.h"

String::String(const char *cstring) {
    assign(cstring);
}

String::String(const String &string) {
    assign(string.m_cstring);
}

String::~String() {
    assign(NULL);
}

String &String::operator=(const char *cstring) {
    return assign(cstring);
}

String &String::operator=(const String &string) {
    return assign(string.m_cstring);
}

String String::operator+(const char *cstring) {
    String str;
    char *newCString = join(this->m_cstring, cstring);
    if (newCString) {
        // 釋放舊的堆空間
        str.assign(NULL);
        // 直接指向新開辟的堆空間
        str.m_cstring = newCString;
    }
    return str;
}

String String::operator+(const String &string) {
    return operator+(string.m_cstring);
}

String &String::operator+=(const char *cstring) {
    char *newCString = join(this->m_cstring, cstring);
    if (newCString) {
        this->assign(NULL);
        this->m_cstring = newCString;
    }
    return *this;
}

String &String::operator+=(const String &string) {
    return operator+=(string.m_cstring);
}

bool String::operator>(const char *cstring) {
    if (!this->m_cstring || !cstring) return 0;
    return strcmp(this->m_cstring, cstring) > 0;
}

bool String::operator>(const String &string) {
    return operator>(string.m_cstring);
}

char String::operator[](int index) {
    if (!this->m_cstring || index < 0) return '\0';
    if (index >= strlen(this->m_cstring)) return '\0';
    return this->m_cstring[index];
}

char *String::join(const char *cstring1, const char *cstring2) {
    if (!cstring1 || !cstring2) return NULL;

    char *newCString = new char[strlen(cstring1) + strlen(cstring2) + 1] {};
    strcat(newCString, cstring1);
    strcat(newCString, cstring2);

    cout << "new[] - " << newCString << endl;
    return newCString;
}

String &String::assign(const char *cstring) {
    // 指向一樣的堆空間
    if (this->m_cstring == cstring) return *this;

    // 釋放舊的字符串
    if (this->m_cstring) {
        cout << "delete[] - " << this->m_cstring << endl;

        delete[] this->m_cstring;
        this->m_cstring = NULL;
    }

    // 指向新的字符串
    if (cstring) {
        cout << "new[] - " << cstring << endl;

        this->m_cstring = new char[strlen(cstring) + 1]{};
        strcpy(this->m_cstring, cstring);
    }

    return *this;
}

ostream &operator<<(ostream &cout, const String &string) {
    if (!string.m_cstring) return cout;
    return cout << string.m_cstring;
}

main函數(shù)調(diào)用如下所示:

String str1;
String str2 = "abcdefg";
String str3 = str1 + str2;
str1 += str2 += str3;
str1[0];
str1 = str2;
if(str1 > str2){
            
}

這個字符串封裝功能內(nèi)部維護一個c_cstring大致也有了string差不多的功能,內(nèi)部進行了封裝和抽取,對內(nèi)存管理需要深入的認識。

仿函數(shù)

將一個對象按照函數(shù)一樣來使用,其實是對象內(nèi)部重載了(),外部調(diào)用就像函數(shù)調(diào)用一樣,對比普通函數(shù),它作為對象可以狀態(tài)。

#include <iostream>
using namespace std;

class Sum {
    int m_age;
public:
    Sum(int age) :m_age(age) { }
    int operator()(int a, int b) {
        if (this->m_age > 10) {}
        else {}
        return a + b;
    }
};

int main() {
    Sum sum(20);
    
    //防函數(shù)調(diào)用
    cout << sum(10, 20) << endl;
    //運算符重載調(diào)用
    cout << sum.operator()(10, 20) << endl;

    return 0;
}

關于運算符的重載,有些運算符不能被重載,比如:

  • 對象成員訪問運算符: .
  • 域運算符號:::
  • 三目運算符:?:
  • sizeof
    有些運算符只能重載為成員函數(shù),比如:
  • 賦值運算符:** = **
  • 下標運算符:[]
  • 函數(shù)運算符號:()
  • 指針訪問成員:->
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容