C++运算符重载

什么是运算符重载

对象可以给对象赋值,是因为系统重载了符号“=”。

同样,对象之间可以进行加减乘除等操作,如:

Student s1,s2;
Student s3=s1-s2;

那s3的值到底是多少?
到底是s1和s2身高差?还是平均分差?还是其他属性的差值?

可重载的运算符:

运算符类型运算符
双目算术运算符+ (加),-(减),*(乘),/(除),% (取模)
关系运算符==(等于),!= (不等于),< (小于),> (大于>,<=(小于等于),>=(大于等于)
逻辑运算符||(逻辑或),&&(逻辑与),!(逻辑非)
单目运算符+ (正),-(负),*(指针),&(取地址)
自增自减运算符++(自增),--(自减)
位运算符| (按位或),& (按位与),~(按位取反),^(按位异或),,<< (左移),>>(右移)
赋值运算符=, +=, -=, *=, /= , % = , &=, |=, ^=, <<=, >>=
空间申请与释放new, delete, new[ ] , delete[]
其他运算符()(函数调用),->(成员访问),,(逗号),[](下标)

不可重载的运算符:

运算符描述
.成员访问运算符
.*, ->*成员指针访问运算符
::域运算符
sizeof长度运算符
?:条件运算符
#预处理符号

一定要记住:

  • 单目运算符最好重载为类的成员函数
  • 双目运算符最好重载为类的友元函数


单目运算符

单目运算符只能与一个操作数相结合。

重载语法:

 int operator++ () {}

解释:

  • 重载的符号为自增运算符++
  • 函数名需要指定为operator,是固定的。
  • 返回值的类型为int,可以自定义。
因为单目运算符通常是对类的成员进行修改,所以最好定义成类的成员函数。

示例-重载符负号:

class Point
{
private:
    float x;
    float y;
public:
    Point(float X, float Y){
        x=X;
        y=Y;
    }
    void print(){
        printf("%-7.2f%-7.2f\n",x,y);
    }
    Point operator- ()      //重载负号
    {
        return Point(-x,-y);    //返回一个新对象,原对象不变
    }
};
int main()
{
    Point p1=Point(1,1);
    Point p2=-p1;
    p1.print();     //p1不变
        p2.print();     //p2为p1取反
}

示例-重载自增/自减运算符:

class Student
{
private:
    int id;
    char* name;
    int age;
public:
    Student(int id, char* name,int age){
        this->id=id;
        this->name=name;
        this->age=age;
    }
    void print(){
        printf(%-5d%-6s%d\n”,id,name,age);
    }
    int operator++ ()       //前置自增
    {
        age++;
        return age;
    }
    int operator++ (int)       //后置自增(int为固定用法)
    {
        age++;
        return age-1;
    }
};
int main()
{
    Student s1=Student(1,"Tom",18);
    cout<<"前置自增:"<<++s1<<endl;
    s1.print();
    cout<<"后置自增:"<<s1++<<endl;
    s1.print();
}


双目运算符

双目运算符可以和两个操作数相结合。比如+,左操作数+右操作数。

语法
Point operator+(Point p1,Point p2){
	……
}
因为双目运算符通常是两个类的状态进行结合,所以最好定义成类的友元函数。
示例-重载+号:
class Point
{
public:
    float x;
    float y;
    Point(float X, float Y){
        x=X;
        y=Y;
    }
    void print(){
        printf("%-7.2f%-7.2f\n",x,y);
    }
    friend Point operator+(Point p1,Point p2);      //声明友元函数
};

//重载+号
//第一个参数是左操作数
//第二个参数是右操作数
Point operator+(Point p1,Point p2)                  //定义友元函数
{
    return Point(p1.x+p2.x,p1.y+p2.y);        //双目运算符一般不改变原对象的状态
}

int main()
{
    Point p1=Point(1,1);
    Point p2=Point(2,2);
    Point p3=p1+p2;   //p3为Point(3,3)
    p3.print();
}


输入输出运算符重载

输出运算符重载
class Student
{
public:
    char* name;
    int age;
    Student(char *NAME, int AGE){
        name=NAME;
        age=AGE;
    }
};
ostream & operator<<(ostream &out, Student &obj){       //重载运算符<<
    out << obj.name << " " << obj.age <<endl;
    return out;     	//返回ostream,可以连续输出
}
int main(){
    Student s1=Student("张三",18);
    cout<<s1<<endl;     //直接输出对象
}

解释:

参数1:ostream实例化的对象,名字可以自定义,这里为out,用于输出。
参数2:需要重载输出运算符的类
返回值:需要ostream &类型,这样就可以连续输出了。

输入运算符重载
class Student
{
public:
    char name[10];
    int age;
};
istream & operator>>(istream &in, Student &obj)
{
    in >> obj.name>> obj.age;
    if (!in)
    {
        obj = Student();	//如果没有输入则初始化对象
    }
    return in;		//返回istream的对象,可以连续输入
}
int main(){
    Student s1;
    cin>>s1;		//输入对象
    cout<<s1.name<<" "<<s1.age<<endl;
}

解释:

与输出运算符重载不一样的是:需要判断用户是否直接回车,什么都没有输入
,还有类似的输入错误。



括号运算符重载

函数调用运算符()重载
class Student{
public:
    char* name;
    int age;
    float avg;
    Student(char* name, int age){
        this->name=name;
        this->age=age;
        avg=0;
    }
    void operator()(int chinese, int math, int english){    //给avg赋值为平均分
        	avg=(chinese + math + english)/3.0;
    }
};
int main(){
    Student s1("张三",18);
    s1(95,96,94);    //使用符号()
    cout<<s1.avg<<endl;	//结果:95
}

解释:

相当于给对象添加了一个新的函数,只不过调用方式是:对象名()

下标运算符重载
class SafeArr{
public:
    int arr[10];
    SafeArr(){
        for(int i = 0; i < 10; i++){
            arr[i] = i;
        }
    }
    int& operator[](int i){
        if( i >= 10 || i<0 ){
            cout << "索引超出范围" <<endl;
            return arr[0];  //返回第一个元素
        }
        return arr[i];
    }
};
int main(){
    SafeArr A;
    cout << "A[2] 的值为 : " << A[2] <<endl;
    cout << "A[5] 的值为 : " << A[5]<<endl;
    cout << "A[-1] 的值为 : " << A[-1]<<endl;
}

posted @ 2020-05-23 19:37  NetRookieX  阅读(5)  评论(0编辑  收藏  举报