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;
}

 

 

posted @ 2021-08-16 15:37  yiwenzhang  阅读(125)  评论(0编辑  收藏  举报