1. 程式人生 > 其它 >c++學習 --- 類和物件之運算子過載

c++學習 --- 類和物件之運算子過載

五、運算子過載

1、加號運算子過載

#include <iostream>
#include <string>
using namespace std;
​
//加號運算子過載
class Person {
public:
    //1.成員函式過載+號
    Person operator+(Person &p) {
        Person temp;
        temp.m_A = this->m_A + p.m_A;
        temp.m_B = this->m_B + p.m_B;
        return temp;
    }
    
int m_A; int m_B; }; ​ ​ //2.全域性函式過載+號 //Person operator+(Person &p1, Person &p2) { // Person temp; // temp.m_A = p1.m_A + p2.m_A; // temp.m_B = p1.m_B + p2.m_B; // return temp; //} ​ ​ //運算子過載也可以發生函式過載 Person operator+(Person &p1, int num) { Person temp; temp.m_A = p1.m_A + num; temp.m_B
= p1.m_B + num; return temp; } void test01() { Person p1; p1.m_A = 10; p1.m_B = 10; Person p2; p2.m_A = 10; p2.m_B = 10; ​ //成員函式過載本質呼叫 //Person p3 = p1.operator+(p2); //全域性函式過載本質呼叫 //Person p3 = operator+(p1, p2); //簡寫成 Person p3 = p1 + p2; //運算子過載也可以發生函式過載
Person p4 = p1 + 100; ​ cout << "p3.m_A = " << p3.m_A << endl; cout << "p3.m_B = " << p3.m_B << endl; ​ cout << "p4.m_A = " << p4.m_A << endl; cout << "p4.m_B = " << p4.m_B << endl; } ​ int main() { test01(); ​ system("pause"); return 0; }

2、左移運算子過載

#include <iostream>
#include <string>
using namespace std;

//左移運算子過載
class Person {
    //過載左移運算子配合友元可以實現輸出自定義資料型別
    friend ostream & operator<<(ostream &out, Person &p);

public:    
    Person(int a, int b) :m_A(a),m_B(b){
    }
    
    //1.利用成員函式過載左移運算子
    
    //不會利用成員函式過載<<運算子,因為無法實現cout在左側
    /*
    void operator<<(Person &p) ==> p.operator<<(p) 不合適
    void operator<<(cout) ==> p.operator<<(cout)  
    簡化版本 p << cout ,cout不在左側,不合適
    */

private:
    int m_A;
    int m_B;
};



//2.利用 全域性函式實現左移運算子

/*本質  operator<<(cout,&p)  簡化 cout << p
ostream 輸出流物件只能有一個,用引用的方式引數傳遞
返回ostream 鏈式程式設計思想可以用於追加輸出別的內容
*/
ostream & operator<<(ostream &out,Person &p) {
    //友元支援訪問類中私有成員變數
    out << "m_A = " << p.m_A << " m_B = " << p.m_B;
    return out;
}

void test01() {
    //建構函式賦初值
    Person p(10,10);
    
    //鏈式程式設計 
    //<< 返回ostream的物件 可以後面輸出<< " Hello world" << endl;
    cout << p << " Hello world" << endl;
}
int main() {
    test01();

    system("pause");
    return 0;
}
3、遞增運算子過載

#include <iostream>
#include <string>
using namespace std;
​
//過載遞增運算子
//自定義整形
class MyInterger {
    friend ostream& operator<<(ostream& cout, MyInterger myint);
public:
    MyInterger():m_Num(0){}
    //過載前置++運算子
    //為什麼返回引用,不返回值
    /*
        和真實前置++一致
        ++(++a)  2 
        a        2
​
        而返回值:
        ++(++myint) 2
        myint   1
​
        前後兩次不是一個物件,第一次加後對新的物件做了遞增
​
    */
    MyInterger& operator++() {
        m_Num++;       //先++
        return *this;  //再將自身做返回
    }
    
    //過載後置++運算子
    /*
        void operator++(int)
        其中int代表佔位引數
        可以用於區分前置和後置(只認int)
​
        為什麼返回值,不返回引用
        返回區域性物件,當前函式執行完後釋放,物件被釋放
        返回引用,後續是非法操作
    */
    MyInterger operator++(int) {        
        MyInterger temp = *this; //先記錄當時的結果 
        m_Num++;        //後遞增       
        return temp;  //最後將記錄結果返回
    }
private:
    int m_Num;
};
​
//全域性函式 << 運算子過載
ostream& operator<<(ostream& cout, MyInterger myint) {
    cout << myint.m_Num;
    return cout;
}
​
void test01() {
    MyInterger myint;
    cout << ++(++myint) << endl;  //2
    cout << myint << endl;        //2
}
​
void test02() {
    MyInterger myint;
    cout << myint++ << endl;  //0
    cout << myint << endl;    //1
}
​
int main() {
    test01();
    //test02();
​
    system("pause");
    return 0;
}
#include <iostream>
#include <string>
using namespace std;
​
//過載遞減運算子
class MyInterger {
    friend ostream& operator<<(ostream & cout, MyInterger mint);
public:
    MyInterger() :m_Num(10) {}
​
    //前置--
    MyInterger& operator--() {
        --m_Num;
        return *this;
    }
    //後置--
    MyInterger operator--(int) {
        MyInterger temp = *this;
        m_Num--;
        return temp;
    }
private:
    int m_Num;
};
​
ostream& operator<<(ostream & cout, MyInterger mint) {
    cout << mint.m_Num;
    return cout;
}
​
void test01() {
    MyInterger myint;
    cout << --(--myint) << endl;  //8
    cout << myint << endl;        //8
}
​
void test02() {
    MyInterger myint;
    cout << myint-- << endl;  //10
    cout << myint << endl;    //9
}
​
int main() {
    test01();
    test02();
​
    system("pause");
    return 0;
}
4、賦值運算子過載

#include <iostream>
#include <string>
using namespace std;
​
//賦值運算子過載
class Person {
public:
    Person(int age) {
        m_Age = new int(age);  //堆區
    }
​
    ~Person() {
        if (m_Age != NULL) {
            delete m_Age;      //手動釋放
            m_Age = NULL;
        }
    }
​
    //過載賦值運算子
    Person& operator=(Person &p) {
        //編譯器提供的時淺拷貝
        //m_Age = p.m_Age;
//應該先判斷是否有屬性在堆區,如果有,先釋放乾淨,然後再深拷貝
        if (m_Age != NULL) {
            delete m_Age;
            m_Age = NULL;
        }
        //深拷貝
        m_Age = new int(*p.m_Age);
        return *this;
    }
    int * m_Age;
};
​
void test01() {
    Person p1(18);
    Person p2(20);
    Person p3(30);
    p1 = p2 = p3;   //賦值操作,預設淺拷貝,在解構函式釋放時暴露問題
    cout << "p1的年齡: " << *p1.m_Age << endl;
    cout << "p2的年齡: " << *p2.m_Age << endl;
    cout << "p3的年齡: " << *p3.m_Age << endl;
}
int main() {
    test01();
​
    system("pause");
    return 0;
}
5、關係運算符過載

#include <iostream>
#include <string>
using namespace std;
​
//關係運算符過載
class Person {
public:
    Person(string name, int age) {
        m_Name = name;
        m_Age = age;
​
    }
    //過載 == 號
    bool operator==(Person &p) {
        if (this->m_Name == p.m_Name && this->m_Age == p.m_Age) {
            return true;
        }
        else
            return false;
    }
​
    //過載 != 號
    bool operator!=(Person &p) {
        if (this->m_Name == p.m_Name && this->m_Age == p.m_Age) {
            return false;
        }
        else {
            return true;
        }
    }
    string m_Name;
    int m_Age;
};
​
void test01() {
    Person p1("Tom", 18);
    Person p2("Tom", 18);
    if (p1 == p2) {
        cout << "p1和p2是相等的" << endl;
    }
    else {
        cout << "p1和p2是不相等的" << endl;
    }
    if (!(p1 != p2)) {
        cout << "p1和p2是相等的" << endl;
    }
    else {
        cout << "p1和p2是不相等的" << endl;
    }
}
​
int main() {
    test01();
​
    system("pause");
    return 0;
}

6、函式呼叫運算子過載

#include <iostream>
#include <string>
using namespace std;
​
//函式呼叫運算子過載
//列印類
class Myprint {
public:
    void operator()(string text) {
        cout << text << endl;
    }
};
​
//加法類
class Myadd {
public:
    int operator()(int num1,int num2) {
        return num1 + num2;
    }
};
​
void MyPrint02(string text) {
    cout << text << endl;
}
​
void test01() {
    Myprint myFunc;
    //仿函式,使用起來非常類似於函式呼叫
    myFunc("hello world");    //物件使用過載的小括號
    MyPrint02("hello world"); //函式呼叫
}
​
//仿函式非常靈活,沒有固定的寫法
void test02() {
    Myadd myadd;
    int ret = myadd(100,100);
    cout << "ret = " << ret << endl;
​
    //匿名函式物件,Myadd();(100,100) 過載的函式呼叫運算子
    cout << Myadd()(100, 200) << endl;
}
​
int main() {
    test01();
    test02();
​
    system("pause");
    return 0;
}