运算符重载

不能重载的运算符有:. 和 :: 和 ?:和.*和sizeof

注意点1:
使用运算符重载的本质上是一次函数调用,所以这些关于运算对象的求值顺序无法应用到重载的运算符上。

友元函数和成员函数的使用场合:
一般情况下,建议一元运算符使用成员函数,二元运算符使用友元函数

1、运算符的操作需要修改类对象的状态,则使用成员函数。如需要做左值操作数的运算符(如 =,+=,++)

2、运算时,有数和对象的混合运算时,必须使用友元

3、二元运算符中,第一个操作数为非对象时,必须使用友元函数。如输入输出运算符 << 和 >>

4、当一个重载运算符是成员函数时,this 绑定到左侧运算对象。成员运算符函数的显式形参比运算对象的数量少一个

5、可以直接调用一个重载的运算符函数,如 operator+(data1, data2), data1.operator(data2)

6、当运算符作用于内置类型对象时,我们无法改变运算符的含义

如下运算符建议使用
所有一元运算符成员函数
= ( ) [ ] ->必须是成员函数
+= -= /= *= ^= &= != %= >>= <<= , 似乎带等号的都在这里了.成员函数
所有其它二元运算符, 例如: –,+,*,/友元函数
<< >>必须是友元函数

注意点2当参数不会被改变,一般按 const 引用来传递(若是使用成员函数重载,函数也为 const).对于返回数值的决定:
1) 如果返回值可能出现在 = 号左边, 则只能作为左值, 返回非 const 引用。
2) 如果返回值只能出现在 = 号右边, 则只需作为右值, 返回 const 型引用或者 const 型值。
3) 如果返回值既可能出现在 = 号左边或者右边, 则其返回值须作为左值, 返回非 const 引用。
也就是左值为非const,右值const

重载 -> 运算符:
#include<bits/stdc++.h>
using namespace std;
struct Node{
//friend string *operator->();
public :
    string *operator->(){
        return ptr;
    }

    Node(string *s):ptr(s){}
    Node()=default;
private :
    string* ptr;
};
//string* operator->(const Node&x){
//    return  x.ptr;
//}
int main(){
    string s="asdf";
    Node x(&s);
    cout<<x->size();//当 ptr 的类型是内置指针类型时,等价于 (*ptr).mem;
    //当 ptr 的类型是类时,等价于ptr.operator->()->mem;//从这里也可以看出 -> 重载必须是成员函数
    return 0;
}

-> 操作符只能通过成员函数来重载,不能通过友元函数来重载。如果通过友元函数来重载,会报错

->操作符的返回根据类型不同,(返回值 function)的解释也不同。
如果返回类型值内置指针,那么就相当于 解引用一下((*返回值).function );
如果返回类型是类的时候,那么就相当于ptr.operator->()->function。

重载–和++运算符:
#include<bits/stdc++.h>//成员函数
using namespace std;
class Node{
friend void print(ostream&,const Node&);
private:
    int x;
public :
    Node()=default;
    Node(int a):x(a){}
    ~Node(){}
    Node& operator--(){//前缀
        x--;
        return *this;
    }

    const Node& operator--(int){
        const Node& cmp = *this;
         --x;
         return cmp;
    }
};
void print(ostream& os,const Node&it){
    os<<it.x<<endl;
}
int main(){
    Node a(10);
    print(cout,a);
    print(cout,a--);
    print(cout,a);
    print(cout,--a);
    print(cout,a);
}
#include<bits/stdc++.h>//友元
using namespace std;
class Node{
friend void print(ostream&,const Node&);
friend Node& operator--(Node&);
friend const Node operator--(Node&,int);
public :
    Node()=default;
    int x;
};
Node& operator--(Node&it){//先减去
    it.x--;
    return it;
}
const Node operator--(Node&it,int) {//有一个占位符号
    const Node tmp=it;
    it.x--;
    return tmp;
}
void print(ostream & os,const Node&x){os<<x.x<<endl;}
int main(){
    Node a;
    a.x=0;
    print(cout,a--);
    print(cout,a);
    print(cout,--a);
}

注意
需要用一个占位符(虚参数)区分前后缀运算
后置时不要返回引用,不然会返回一个局部对象引用

重载[]运算符:

#include<bits/stdc++.h>
using namespace std;
class Node{
public :
    ~Node(){}
    Node()=default;
    Node(int *a){
        for(int i=0;i<100;i++)x[i]=a[i];
    }
    int operator[](int in){
        if(0<=in&&in<100)return x[in];
        else {
            cout<<"out of range;";
        }
    }
private:
    int x[100];
};

int main(){
    int tmp[100];
    for(int i=0;i<100;i++)tmp[i]=i;
    Node a(tmp);
    cout<<a[2];
}
//【】的重载必须是非静态成员重载

我们可以发现 [] 只能作为成员函数重载,如果重载为友元函数的话会报错:

重载()运算符

我们可以发现 () 只能作为非静态成员函数重载,如果重载为友元函数的话会报错:

#include<bits/stdc++.h>
using namespace std;
class Node{
private :
    int x;
public:
    ~Node(){}
    Node(int a):x(a){}
    const int operator()(const Node &it)const {
        return x+it.x;
    }
};
int main(){
    Node a(10);
    cout<<a(a);
    return 0;
}

重载运算符 () 的目的:对象 () 类似于函数名 (x),更加符合习惯
语法:
重载方式:只能使用成员函数重载
重载后还可以继续重载
函数名:operator( )(参数表)
参数表:参数随意,具体根据实际情况而定。
函数调用:显式调用:Obj(x)
隐式调用:obj.operator( )(x)
返回类型:
1、返回成员的实际类型随意,具体由程序员根据函数体定义
2、因为返回值只能做右值,只读,应该使用返回值为const类型

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

class gel{
// friend ostream& operator<<(const gel&, ostream&);
friend ostream& operator<<(ostream&, const gel&);

private:
    int x, y;

public:
    gel(int a, int b) : x(a), y(b){}
    gel(int a) : gel(a, 0){}
    gel(void) : gel(0, 0){}
    ~gel(){}
};

// ostream& operator<<(const gel &it, ostream &os){
//     os << it.x << " " << it.y;
//     return os;
// }

ostream& operator<<(ostream &os, const gel &it){
    os << it.x << " " << it.y;
    return os;
}

int main(void){
    gel a(1, 2);
    cout << a << endl;
    return 0;
}
#include <iostream>
using namespace std;

class gel{
private:
    int x, y;

public:
    gel(int a, int b) : x(a), y(b){}
    gel(int a) : gel(a, 0){}
    gel(void) : gel(0, 0){}
    ~gel(){}
    
    ostream& operator<<(ostream &os){
        os << this->x << " " << this->y;
        return os;
    }
};

int main(void){
    gel a(1, 2);
    // cout << a << endl;
    //我们可以发现不加这个语句的话这个代码是正确的,再结合前面的东西,我们可以得出这个语句错误的原因:
    //将<<重载成gel类的成员函数,其第一个参数必须是gel类的对象,即要求<<是右结合的(a在<<右边嘛),而<<本身是要求左结合的.此处矛盾所以是错误的
    //那么我们可以尝试着将cout << a << endl;改成既满足<<是左结合的,又满足<<的第一个参数是a
    a.operator << (cout) << endl;//此处cout必须加括号,将opetator<<当成一个a类的成员函数,后面接着的当然是参数列表啦,cout是实参.又因为其返回的是一个cout流,所以后面可以接其它输出内容
    return 0;
}
重载 = 运算符:

= 只能作为成员函数重载,如果重载为友元函数的话会报错:

自己打过ACM,感觉这个东西没什么总结的,
详细总结在这里:https://www.cnblogs.com/geloutingyu/p/8283810.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值