C++运算符重载

引言

运算符重载概念:对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型。

4.5.1 加号运算符的重载

作用:实现两个自定义的数据类型相加。
 

#include <iostream>
#include <string>
using namespace std;
//运算符重载
//对于内置的数据类型,编译器知道如何进行运算

class Person {
public:
    // 1.成员函数重载+
    // Person p3 = p1.operator+(p2);

    //    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 p3 = operator+(p1,p2);
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 + p2;
    Person p3 = operator+(p1, p2);
    cout << p3.m_A << p3.m_B << endl;
    //运算符重载也可以发生函数重载
    Person p4 = p1 + 100;
    cout << p4.m_A << p4.m_B << endl;
}

int main()
{
    test01();
    return 0;
}

总结1:对于内置的数据类型的表达式是不可能改变的
总结2:不要滥用运算符的重载

4.5.2 左移运算符重载

作用:可以输出自定义的数据类型

#include <iostream>
#include <string>
using namespace std;
//运算符重载
//左移运算符 <<
// 输出自定义类型
class Person {
    friend ostream& operator<<(ostream& cout, Person& p); // 声明为类的友元

private:
    int m_A;
    int m_B;

public:
    Person()
    {
        m_A = 10;
        m_B = 20;
    }
    //利用成员函数重载左移运算符 p.operator<<(cout) 简化版本 p<<cout
    //不会利用成员函数重载左移运算符<< ,无法实现cout在左侧
    //    void operator<<(cout)
    //    {
    //        cout << this->m_A << endl;
    //        cout << this->m_B << endl;
    //    }
};
//只能用全局函数重载<<运算符
//本质operator<<(cout ,p)
//简化 cout << p
ostream& operator<<(ostream& cout, Person& p)
{
    cout << p.m_A << endl;
    cout << p.m_B << endl;
    return cout;
}
void test01()
{
    Person p;
 

    cout << p << endl;
}

int main()
{
    test01();
    return 0;
}

总结:重载左移运算符配合友元可以实现输出自定义的数据类型

右移运算符重载

#include <iostream>
using namespace std;

class Student {
public:
    Student(int math = 0, int english = 0, int total = 0) //代表初始值为0,可以给他赋值,传递几个参数都可以,不穿默认0。
        : _math(math)
        , _english(english)
        , _total(total)
    {
    }
    void show()
    {
        cout << _math << " " << _english << " " << _total << endl;
    }

private:
    int _math, _english, _total;
    friend istream& operator>>(istream& in, Student& s);
};

istream& operator>>(istream& in, Student& s)
{
    in >> s._math >> s._english;
    s._total = s._math + s._english;
    return in;
}
int main()
{
    Student s;
    cin >> s;
    s.show();
}

4.5.3 递增运算符重载

作用:通过重载递增运算符,实现自己的整型数据

#include <iostream>
using namespace std;

//递增运算符重载++
//自定义的整型
class MyInteger {
    friend ostream& operator<<(ostream& cout, MyInteger myint);

public:
    MyInteger()
    {
        int m_Num = 0;
    }
    //重载++运算符
    //重载分为两者,前递增
    MyInteger&
    operator++()
    {
        //先进行++运算
        m_Num += 1;
        //再将自身返回,返回需要返回引用,为了对一个数据进行递增.
        return *this;
    }
    //后递增
    // int代表占位参数,可以用来区分前置和后置递增
    MyInteger operator++(int)
    {
        //先记录当时结果
        MyInteger temp = *this;
        //后 递增
        m_Num++;
        // 最后将结果返回
        return temp;
    }

private:
    int m_Num;
};

ostream& operator<<(ostream& cout, MyInteger myint)
{
    cout << myint.m_Num;
    return cout;
}
void test01()
{
    MyInteger myint;
    cout << myint << endl;
    cout << ++myint << endl;
    cout << ++myint << endl;
    cout << myint << endl;
}

void test02()
{
    MyInteger myint;
    cout << myint++ << endl;
    cout << myint << endl;
}
int main()
{
    test02();
    return 0;
}

4.5.4 递减运算符 

#include <iostream>
using namespace std;

//递减运算符重载--
//自定义的整型
class MyInteger {
    friend ostream& operator<<(ostream& cout, MyInteger myint);

public:
    MyInteger()
    {
        int m_Num = 0;
    }
    //重载--运算符
    //重载分为两者,前递减
    MyInteger&
    operator--()
    {
        //先进行--运算
        m_Num--;
        //再将自身返回,返回需要返回引用,为了对一个数据进行递减
        return *this;
    }
    //后递减
    // int代表占位参数,可以用来区分前置和后置递减
    MyInteger operator--(int)
    {
        //先记录当时结果
        MyInteger temp = *this;
        //后 递减
        m_Num--;
        // 最后将结果返回
        return temp;
    }

private:
    int m_Num;
};

ostream& operator<<(ostream& cout, MyInteger myint)
{
    cout << myint.m_Num;
    return cout;
}
void test01()
{
    MyInteger myint;
    cout << myint << endl;
    cout << --myint << endl;
    cout << --myint << endl;
    cout << myint << endl;
}

void test02()
{
    MyInteger myint;
    cout << myint-- << endl;
    cout << myint << endl;
}
int main()
{
    test01();
    return 0;
}

4.5.5 赋值运算符重载

C++编译器至少给一个类添加4个函数
1.默认构造函数(无参,函数体为空)
2.默认析构函数(无参,函数体为空)
3.默认拷贝函数,对属性进行值拷贝
4.赋值运算符operator=,对属性进行值拷贝

如果类中有属性指向堆区,做赋值操作时也会出现深浅拷贝的问题。

#include <iostream>
using namespace std;
//赋值运算符重载
class Person {
public:
    Person(int age)
    {
        m_Age = new int(age);
    }
    int* m_Age;
    //重载=赋值运算符
    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;
    }
    ~Person()
    {
        if (m_Age != NULL) {
            delete m_Age;
            m_Age = NULL;
        }
    }
};

void test01()
{
    Person p1(19);
    Person p2(20);
    Person p3(30);

    p3 = p2 = p1; //赋值运算操作

    cout << "p1的年龄" << *p1.m_Age << endl;
    cout << "p2的年龄" << *p2.m_Age << endl;
    cout << "p3的年龄" << *p3.m_Age << endl;
}

int main()
{
    test01();
    return 0;
}

4.5.6 关系运算符重载

作用:重载关系运算符,可以让两个自定义的类型对象进行比较操作。

#include <iostream>
using namespace std;
//重载关系运算符

class Person {
public:
    Person(string name, int age)
    {
        m_Name = name;
        m_Age = age;
    }
    string m_Name;
    int m_Age;
    bool operator==(Person& p)
    {
        if (this->m_Name == p.m_Name && this->m_Age == p.m_Age) {
            return true;
        }
        return false;
    }
    bool operator!=(Person& p)
    {
        if (this->m_Name == p.m_Name && this->m_Age == p.m_Age) {
            return false;
        }
        return true;
    }
};

void test01()
{
    Person p("张三", 15);
    Person p2("张三s", 15);
    if (p == p2) {
        cout << "p和p2相等" << endl;
    } else {
        cout << "p和p2不相等" << endl;
    }
}

int main()
{
    test01();
    return 0;
}

4.5.7 函数调用运算符重载

函数调用运算符()也可以重载
由于重载后使用的方法非常像函数的调用,因此称为仿函数。
仿函数没有固定的写法,非常灵活。

#include <iostream>
using namespace std;
//打印输出的类
class MyPrint {
    friend void test01();
    //重载函数调用运算符
    void operator()(string test)
    {
        cout << test << endl;
    }
};

void test01()
{
    MyPrint p;
    p("hello world"); //由于使用起来非常类似函数调用,所以我们成为仿函数
}
//仿函数非常灵活,没有固定写法
class MyAdd {
public:
    int operator()(int num1, int num2)
    {
        return num1 + num2;
    }
};

void test02()
{
    MyAdd add;
    cout << add(1, 2) << endl;
    //匿名函数对象 类名加(),匿名对象
    cout << MyAdd()(100, 10) << endl;
}
int main()
{
    test02();
    return 0;
}

运算符重载综合案例

#include <iostream>
using namespace std;

class complex{
public:
    complex(double real = 0.0, double imag = 0.0): m_real(real), m_imag(imag){ };
public:
    friend complex operator+(const complex & A, const complex & B);
    friend complex operator-(const complex & A, const complex & B);
    friend complex operator*(const complex & A, const complex & B);
    friend complex operator/(const complex & A, const complex & B);
    friend istream & operator>>(istream & in, complex & A);
    friend ostream & operator<<(ostream & out, complex & A);
private:
    double m_real;  //实部
    double m_imag;  //虚部
};

//重载加法运算符
complex operator+(const complex & A, const complex &B){
    complex C;
    C.m_real = A.m_real + B.m_real;
    C.m_imag = A.m_imag + B.m_imag;
    return C;
}

//重载减法运算符
complex operator-(const complex & A, const complex &B){
    complex C;
    C.m_real = A.m_real - B.m_real;
    C.m_imag = A.m_imag - B.m_imag;
    return C;
}

//重载乘法运算符
complex operator*(const complex & A, const complex &B){
    complex C;
    C.m_real = A.m_real * B.m_real - A.m_imag * B.m_imag;
    C.m_imag = A.m_imag * B.m_real + A.m_real * B.m_imag;
    return C;
}

//重载除法运算符
complex operator/(const complex & A, const complex & B){
    complex C;
    double square = A.m_real * A.m_real + A.m_imag * A.m_imag;
    C.m_real = (A.m_real * B.m_real + A.m_imag * B.m_imag)/square;
    C.m_imag = (A.m_imag * B.m_real - A.m_real * B.m_imag)/square;
    return C;
}

//重载输入运算符
istream & operator>>(istream & in, complex & A){
    in >> A.m_real >> A.m_imag;
    return in;
}

//重载输出运算符
ostream & operator<<(ostream & out, complex & A){
    out << A.m_real <<" + "<< A.m_imag <<" i ";;
    return out;
}

int main(){
    complex c1, c2, c3;
    cin>>c1>>c2;

    c3 = c1 + c2;
    cout<<"c1 + c2 = "<<c3<<endl;

    c3 = c1 - c2;
    cout<<"c1 - c2 = "<<c3<<endl;

    c3 = c1 * c2;
    cout<<"c1 * c2 = "<<c3<<endl;

    c3 = c1 / c2;
    cout<<"c1 / c2 = "<<c3<<endl;

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值