操作符重載 2025-09-29

操作符重載的作用

使我們可以像基本數(shù)據(jù)類型那樣用運算符;
仿函數(shù)是建立在操作符重載的基礎(chǔ)上的;
stl中容器的算法也是建立在操作符重載的基礎(chǔ)上的;

首先我個人認為去寫操作符重載要掌握的最重要的原則是:你寫的這個重載操作符要傳入幾個參數(shù)。
其原則是看這個操作符重載是不是當(dāng)前類的成員函數(shù),如果是就只需要傳一個參數(shù)(隱含參數(shù):左操作數(shù) (a) 通過 this指針傳遞);如果是類外或者友元等非成員函數(shù)那需要傳兩個參數(shù)

下面寫幾個案例

舉例說明

下面是不能兩中方式一起寫的,這會造成編譯錯誤(二義性錯誤)
對于 +這類不修改左操作數(shù)、通常返回新對象的對稱性運算符,更推薦使用非成員函數(shù)(友元)形式。這樣做還有一個好處:如果你希望支持 (整數(shù) + Complex對象)這樣的表達式,非成員函數(shù)是必須的,因為整數(shù)不是你的類類型,不能作為成員函數(shù)的調(diào)用者。
如果 operator+是成員函數(shù),5 + c1將無法編譯。(c1是Complex的對象)

class Complex{
    public:
        Complex operator+(const Complex& rightOperand) const
        {
            return Complex(real+rightOperand.real,imag+rightOperand.imag);
        }

        friend Complex operator+(const Complex& leftOperand,const Complex& rightOperand);

    private:
        double real,imag;
};

Complex operator+(const Complex& leftOperand,const Complex& rightOperand)
{
    return Complex(leftOperand.real+rightOperand.real,leftOperand.imag+rightOperand.imag);
}


1. 算術(shù)運算符與復(fù)合賦值運算符 (+, +=)

#include <iostream>
class Complex {
private:
    double real;
    double imag;
public:
    Complex(double r = 0.0, double i = 0.0) : real(r), imag(i) {}

    // 復(fù)合賦值運算符 +=,通常作為成員函數(shù)(修改左操作數(shù))
    Complex& operator+=(const Complex& rhs) {
        real += rhs.real;
        imag += rhs.imag;
        return *this; // 返回引用以支持鏈式賦值 (a += b) += c
    }

    // 提供友元函數(shù)形式,以便支持左操作數(shù)為非本類對象的情況
    friend Complex operator+(const Complex& lhs, const Complex& rhs);
};

// 算術(shù)運算符 +,作為非成員友元函數(shù)(不修改操作數(shù),生成新對象)
Complex operator+(const Complex& lhs, const Complex& rhs) {
    return Complex(lhs.real + rhs.real, lhs.imag + rhs.imag);
    // 也可以利用已實現(xiàn)的 += 來提升效率:Complex result(lhs); return result += rhs;
}

int main() {
    Complex a(1.0, 2.0), b(3.0, 4.0);
    Complex c = a + b; // 調(diào)用 operator+(a, b)
    a += b;            // 調(diào)用 a.operator+=(b)
    return 0;
}

2. 關(guān)系運算符 (==, !=)

class Complex {
    // ... 其他成員同上
public:
    // 關(guān)系運算符 ==,通常重載為友元函數(shù)
    friend bool operator==(const Complex& lhs, const Complex& rhs) {
        return (lhs.real == rhs.real) && (lhs.imag == rhs.imag);
    }

    // 關(guān)系運算符 !=,通常利用 == 來實現(xiàn)
    friend bool operator!=(const Complex& lhs, const Complex& rhs) {
        return !(lhs == rhs);
    }
};

3. 輸入與輸出運算符 (>>, <<)

class Complex {
    // ... 其他成員同上
public:
    // 輸入輸出運算符必須重載為非成員函數(shù)
    friend std::ostream& operator<<(std::ostream& os, const Complex& c) {
        os << c.real << " + " << c.imag << "i";
        return os; // 返回流引用以支持鏈式操作 cout << a << b;
    }

    friend std::istream& operator>>(std::istream& is, Complex& c) {
        is >> c.real >> c.imag;
        return is; // 返回流引用以支持鏈式操作 cin >> a >> b;
    }
};

4. 下標運算符 ([])

下標運算符 []必須重載為類的成員函數(shù)。為了同時支持常量對象和非常量對象的使用,通常需要提供兩個版本。

class MyArray {
private:
    int data[100];
    size_t size;
public:
    MyArray(size_t s = 100) : size(s) {}

    // 非常量版本:允許通過下標修改數(shù)組元素
    int& operator[](size_t index) {
        if (index >= size) throw std::out_of_range("Index out of range");
        return data[index];
    }

    // 常量版本:用于常量對象,只允許讀取,返回 const 引用
    const int& operator[](size_t index) const {
        if (index >= size) throw std::out_of_range("Index out of range");
        return data[index];
    }
};

int main() {
    MyArray arr;
    arr[10] = 42;        // 調(diào)用非常量版本,可以賦值
    std::cout << arr[10]; // 調(diào)用非常量版本,可以讀取

    const MyArray const_arr;
    // const_arr[10] = 50; // 錯誤!調(diào)用常量版本,不能賦值
    std::cout << const_arr[10]; // 正確,調(diào)用常量版本,可以讀取
    return 0;
}

5. 遞增與遞減運算符 (++, --)

遞增和遞減運算符有前置和后置兩種形式,需要通過參數(shù)來區(qū)分。

class Counter {
private:
    int count;
public:
    Counter(int c = 0) : count(c) {}

    // 前置 ++:無參數(shù),返回遞增后的引用
    Counter& operator++() {
        ++count;
        return *this;
    }

    // 后置 ++:int 參數(shù)僅用于區(qū)分,無實際意義,返回遞增前的副本(值)
    Counter operator++(int) {
        Counter temp = *this; // 保存原值
        ++(*this);           // 利用前置 ++ 實現(xiàn)遞增
        return temp;         // 返回原值
    }

    // 前置 -- 和后置 -- 類似
    Counter& operator--() {
        --count;
        return *this;
    }
    Counter operator--(int) {
        Counter temp = *this;
        --(*this);
        return temp;
    }
};

stl容器算法 (自定義排序規(guī)則)

使用重載的 < 運算符進行排序

#include <algorithm>
#include <vector>
#include <string>

struct Person
{
    std::string name;
    int age;
    bool operator<(const Person& other) const
    {
        return age<other.age;
    }
};

int main()
{
    std::vector<Person> people = {{"Alice", 25}, {"Bob", 20}, {"Charlie", 30}};

    std::sort(people.begin(),people.end()); 
    return 0;
}

使用仿函數(shù)

#include <algorithm>
#include <vector>
#include <string>
#include <iostream>

std::vector<int> numbers={3,1,4,1,5,9,2,6};
std::sort(numbers.begin(),numbers.end(),std::greator<int>());

struct LengthCompare
{
    bool operator()(const std::string& a,const std::string& b) const
    {
        return a.length()<b.length();
    }
}

std::vector<std::string> words={"apple","a","banana","cat"};
std::sort(words.begin(),words.end(),LengthCompare());

——

條件查找和計數(shù) 也常自定義邏輯

同樣可以使用類成員函數(shù)重載操作符,也可以使用自定義仿函數(shù)



class GreaterThan
{
    public:
    GreaterThan(int threshold):threshold_(threshold) {}
    bool operator()(int x) const {return x>threshold_;}

    private:
        int threshold_;
};

int main()
{
    std::vector<int> scores={85,92,76,60,99,45};
    //統(tǒng)計滿足條件的數(shù)量有多少個(其實用lamada表達式顯得邏輯更清晰,但用仿函數(shù)增加了復(fù)用性)
    int count=std::count_if(scores.begin(),scores.end(),GreaterThan(80));
    std::cout<<"大于80分的數(shù)量: "<<count<<std::endl;

    //使用find_if 在范圍內(nèi)查找第一個滿足特定條件的元素 返回的是迭代器
    auto it_25=std::find_if(socres.begin(),socres.end(),[](int n){return n==25;}
    if(it_25!=scores.end())
    {
        std::cout << "第一個等于25的元素: " << *it_25 << ",位于索引 " << (it_25 - scores.begin()) << std::endl; // 輸出: 第一個等于25的元素: 25,位于索引 1
    }
    return 0;
}

變換元素

#include <algorithm>
#include <vector>
#include <iostream>

// 自定義仿函數(shù):將元素乘以2
class MultiplyByTwo {
public:
    int operator()(int x) const { return x * 2; }
};

int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5};
    std::vector<int> result(vec.size());
    
    std::transform(vec.begin(), vec.end(), result.begin(), MultiplyByTwo());
    // result = {2, 4, 6, 8, 10} [1,3](@ref)
    
    return 0;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

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