C++运算符重载详解

四则运算符

class Person {  
public:  
    Person() {};  
    Person(int a, int b)  
    {  
        this->m_A = a;  
        this->m_B = b;  
    }  

    // 成员函数实现 + 号运算符重载  
    Person operator+(const Person& p) {  
        Person temp;  
        temp.m_A = this->m_A + p.m_A;  
        temp.m_B = this->m_B + p.m_B;  
        return temp;  
    }
private:  
    int m_A;  
    int m_B;  
};  
// 全局函数实现 + 号运算符重载  
Person operator+(const Person& p1, const Person& p2) {  
    Person temp(0, 0);  
    temp.m_A = p1.m_A + p2.m_A;  
    temp.m_B = p1.m_B + p2.m_B;  
    return temp;  
}
// 成员函数和全局函数实现后的调用
Person p = p1 + p2;
// 运算符重载版本
Person operator+(const Person& p2, int val)  
{
    Person temp;
    temp.m_A = p2.m_A + val;
    temp.m_B = p2.m_B + val;
    return temp;
}
// 调用
Person p = p1 + 10;

本质调用

// 成员函数
Person p = p1.operator+(p2);
// 全局函数
Person p = operator+(p1, p2);

其他运算符和 + 类似,只是注意精度别爆 int 以及除法特判除数为 0 情况

左移运算符

class Person {
    // 设置友元,因为全局函数要使用私有变量
    friend ostream& operator<<(ostream& out, Person& p);  
public:
    Person(){}
    Person(int a, int b)  
    {
        this->m_A = a;  
        this->m_B = b;  
    }
  
    // 成员函数 实现不了
    // void operator<<(cout) {  
    // }  
    // 直接传 cout 肯定有问题,只是方便理解,传对应的数据类型,cout 是个 ostream 输出流对象,传 ostream
    // 这样是 p << cout 不是我们想要的效果,虽然用成员函数这样写实现后,我们 p << cout 也能正确输出
    // 因为成员函数里本质是用 p 去调用 << 运算符
private:
    int m_A;  
    int m_B;  
};

// 全局函数实现左移重载  
// ostream对象只能有一个
// 本质是 operator<< (cout, p)  ----> cout << p
ostream& operator<<(ostream& cout, Person& p) {  
    cout << "a:" << p.m_A << " b:" << p.m_B;  
    return out;  
}
// 这里面引用缘故,还可使用 out 起别名
ostream& operator<<(ostream& out, Person& p) {  
    out << "a:" << p.m_A << " b:" << p.m_B;  
    return out;  
}
// 外部输出还是 cout
cout << p;
  • 注意传参和返回值都需要引用的存在
  • 因为标准输出流对象只能有一个,所以不能创建副本,返回值自然也不能传值
  • 返回值传引用是因为
  • 调用过程是:执行 cout << p ,左移运算符做了重载,传入 coutp
  • 然后执行函数体,就实现了重载,这里相当于是 ostream& out = cout

为了实现链式编程,返回值为 ostream& ,这样之后就可以 cout << p << endl

递增运算符

class MyInteger {
    friend ostream& operator<<(ostream& out, MyInteger myint);
public:  
    MyInteger() {  
        m_Num = 0;  
    }  
    // 前置++
    MyInteger& operator++() {  
        //先++  
        m_Num++;  
        //再返回  
        return *this;  
    }  
  
    // 后置++
    // int 是占位符,表示 a++
    MyInteger operator++(int) {  
        // 先返回  
        // 记录当前本身的值,然后让本身的值加1,但是返回的是以前的值,达到先返回后++;
        MyInteger temp = *this; 
        m_Num++;  
        return temp;  
    }
    
private:  
    int m_Num;  
};

ostream& operator<<(ostream& out, MyInteger myint) {  
    out << myint.m_Num;  
    return out;  
}

// 调用
MyInter a;
cout << ++(++a);
cout << a++;
// 不存在 cout << (a++)++;
  • 前置加加返回引用是因为存在 ++(++a) 这种情况,我们要实现这种,就需要返回引用
  • 因为不返回引用,第一次 ++a 后是创建的一个副本即新对象作为 ++a 的结果,那么此时再执行 ++a 虽然能够使 ++(++a) 得到正确的结果,但是 a 却不是,因为第二次的加加不是在 a 基础上的加,是一个新的副本
  • 值返回不能是因为不能返回局部引用,第二种方式会构造局部引用

赋值运算符

class Person {
public:
    Person() : m_age(nullptr){}
    Person(int age) {
        m_Age = new int(age);
    }

    //重载赋值运算符 
    Person& operator=(const Person &p)
    {
        if (m_Age != NULL) {
            delete m_Age;
            m_Age = NULL;
        }
        //编译器提供的代码是浅拷贝
        //m_Age = p.m_Age;

        //提供深拷贝 解决浅拷贝的问题
        m_Age = new int(*p.m_Age);

        //返回自身
        return *this;
    }

    ~Person()
    {
        if (m_Age != NULL) {
            delete m_Age;
            m_Age = NULL;
        }
    }
private:
    int *m_Age;
};

// 调用
Person p1(10);
Person p2, p3;
p3 = p2 = p1;
  • 注意实例化对象不初始化,需要在默认构造函数里指针指向空,不然是野指针,随意指向一块空间,此时进入拷贝构造函数,就会释放非法内存,导致崩溃
  • 这是应对指针的拷贝构造函数,默认拷贝构造会造成释放同一块内存区域的问题,导致出错
  • 对于这种类型的传引用,使用 const 修饰会更好,防止意外修改

关系运算符

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

// 调用
Person a("孙悟空", 18);
Person b("孙悟空", 18);
if(a == b) 
else if(a != b)

函数调用运算符 ( )

class MyPrint {  
public:  
    void operator()(string text) {  
        cout << text << endl;  
    }  
};  

// 调用
MyPrint myFunc;  
myFunc("hello world");  
class MyAdd {  
public:  
    int operator()(int v1, int v2) {  
        return v1 + v2;  
    }  
};

// 调用
MyAdd add;
int ret = add(10, 10);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值