C++运算符重载

一.加号运算符重载

1.成员函数重载加号
#include<iostream>

using namespace std;

class Person{
public:
    int age_A;
    int age_B;

    Person operator+(Person p1){//成员函数重载了+号
        Person temp;
        temp.age_A=0;
        temp.age_B=0;
        temp.age_A=this->age_A+p1.age_A;
        temp.age_B=this->age_B+p1.age_B;
        return temp;
    }
};

int main(){
    Person p1;
    p1.age_A=10;
    p1.age_B=100;
    Person p2;
    p2.age_A=10;
    p2.age_B=100;
    Person p3=p1+p2;//‘+’为重载之后的‘+’
    cout<<p3.age_A<<endl;
    cout<<p3.age_B<<endl;
}

将函数名命名为operator+,就可以对‘+’进行重载

2.全局函数重载加号
#include<iostream>

using namespace std;


class Person{
public:
    int age_A;
    int age_B;
};

Person operator+(Person p1,Person p2){
        Person temp;
        temp.age_A=0;
        temp.age_B=0;
        temp.age_A=p1.age_A+p2.age_A;
        temp.age_B=p1.age_B+p1.age_B;
        return temp;
}

int main(){
    Person p1;
    p1.age_A=10;
    p1.age_B=100;
    Person p2;
    p2.age_A=10;
    p2.age_B=100;
    Person p3=p1+p2;
    cout<<p3.age_A<<endl;
    cout<<p3.age_B<<endl;
}

原理和成员函数基本相同,返回值为类型,区别只是参数变成了两个类

二.左移运算符重载

左移运算符和加号运算符不同,如果在成员函数中进行重载,那么不能达到预期效果,这里通常只能在全局函数中重载

#include<iostream>

using namespace std;

class Person{
public:
    int m_A;
    int m_B;
};

ostream& operator<<(ostream& t,Person& p){
        t<<"m_A="<<p.m_A<<" m_B="<<p.m_B<<endl;
        return t;
}

int main(){
    Person p1;
    p1.m_A=10;
    p1.m_B=10;
    cout<<p1<<endl;
    Person p2;
    p2.m_A=20;
    p2.m_B=20;
    cout<<p2<<endl;

    
}

1.注意看operator<<函数,将ostream类型进行改写,这里一定要是引用,否则后续在使用时会报错。

2.在最后返回了一个ostream的引用,是为了支持链式操作。(因为当我们使用 ostream 对象进行输出时,通常会进行链式操作,比如 cout << "Hello" << endl;。这是因为 << 运算符会返回其左操作数的引用,以便我们可以继续在其上执行输出操作。如果 ostream 对象作为值传递,那么每次 << 运算符调用都会生成一个新的 ostream 对象,导致链式操作失效。)

三.递增运算符重载

#include<iostream>

using namespace std;

class MyInt{
    
    //设置为友元,访问私有成员变量
    friend ostream& operator<<(ostream& cout,const MyInt &i);

public:

    MyInt(){
        num=0;
    }

    //前置自增运算符
    MyInt& operator++()
    {
        //先进行++运算
        num++;
        //再将自身返回
        return *this; 
    }

    // 后置自增运算符
    // int代表占位参数,可以用于区分前置和后置自增
    MyInt operator++(int)
    {
        MyInt temp = *this;
        num++;
        return temp;
    }

private:
    int num;
};

ostream& operator<<(ostream& cout,const MyInt &i){
    cout << i.num;
    return cout;
}


int main(){
    MyInt myint;
    cout << ++(++myint) <<endl;
    
    cout << myint++ << endl;

    cout << myint <<endl;

}

注意看前置运算和后置运算的区别

前置递增时最后返回的是一个类的引用,这是因为前置递增一般可以进行链式操作。而后置运算符返回的是对象递增前的值的副本,因此不能进行链式操作。

链式操作详解:

在表达式 cout << a << b; 中,编译器会从左向右逐个解析表达式,并根据运算符的优先级和结合性确定表达式的含义。在这个例子中,<< 是左结合的,因此编译器会首先解析 cout << a 这个子表达式。

因此,编译器首先识别的是 cout << a 这一部分。它会查找一个与左操作数 cout 和右操作数 a 匹配的重载运算符 <<。由于标准库中已经定义了 cout<< 运算符,它将 a 的值输出到 cout 中,并返回一个 ostream& 对象,表示输出流本身。

然后,编译器将这个返回的 ostream& 对象视为整个表达式的左操作数,接着解析 << b 部分。同样地,编译器会查找与左操作数匹配的重载运算符 <<,并将 b 的值插入到输出流中。

四.赋值运算符重载

#include<iostream>

using namespace std;

class Person{
public:
    Person& operator=(Person &p){
        //如果之前m_Age已经有数据了,那么要先销毁
            if(m_Age!=nullptr){
                delete m_Age;
                m_Age=nullptr;
            }
            m_Age=new int(*p.m_Age);//这里进行深拷贝操作,防止在构析函数中销毁堆区中的数据时进行重复销毁操作
            return *this;
    }
    
    ~Person()//析构函数释放之前new在堆区的数据
    {
        if(m_Age!=nullptr)
        {
        delete m_Age;
        m_Age=nullptr;
        }
    } 

    Person(int age){
        m_Age=new int(age);
    }

    int* m_Age;
};

int main(){
    Person p1(18);
    Person p2(20);
    Person p3(30);

    p1=p2=p3;
    cout<< *(p1.m_Age)<<endl;
}

注意点:

在赋值重载函数中,对m_Age这种指针类型的赋值采用了深拷贝的方法,这是因为每一次赋值如果采用浅拷贝的话,最后在析构函数中就会重复删除已经为空的m_Age,导致编译器出错

五.关系运算符重载

重载==号以及重载!=号

#include<iostream>

using namespace std;

class Person{
public:
    Person(string name,int m_Age){
            this->name=name;
            this->m_Age=m_Age;
    }
    //重载==运算符
    bool operator==(Person &p){
        if(this->m_Age==p.m_Age&&this->name==p.name){
            return true;
        }else{
            return false;
        }
    }
    //重载!=运算符
    bool operator!=(Person &p){
        if(this->m_Age==p.m_Age&&this->name==p.name){
            return false;
        }else{
            return true;
        }
    }


    string name;
    int m_Age;
};

void test(){
    Person p1("黎明",50);
    Person p2("刘德华",55);
    Person p3("黎明",50);

    if(p1==p3){
        cout<<"p1和p3是一样的"<<endl;
    }
    if(p1!=p2){
        cout<<"p1和p2是不一样的"<<endl;
    }else{
        cout<<"p1和p2是一样的"<<endl;
    }
}
int main(){
    test();
}

这个非常简单,只需要返回一个bool类型的值就可以

五.函数调用运算符重载

#include<iostream>

using namespace std;

class Myprint{
public:
    //函数调用运算符重载
    void operator()(string content){
            cout<<content<<endl;
    }
};

void test(){
    Myprint print;
    print("ppthat1");
}
void print(string s){
    cout<<s<<endl;
}

int main(){
    test();
    print("nihaow");
}

注意看,这个重载的()操作符由于非常像一个函数,因此称为仿函数。仿函数没有固定的写法,因此非常灵活

  • 7
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值