Bootstrap

C++运算符重载

目录

一. 前言

二. 加号运算符重载

 三. 左移运算符重载

四.  递增运算符重载

五. 赋值运算符重载

六. 关系运算符重载

 七. 函数调用运算符重载


一. 前言

        C++运算符的重载总共可以分为六种,分别为加号运算符重载,左移运算符重载,递增运算符重载,赋值运算符重载,关系运算符重载,函数调用运算符重载。下面我来分别介绍这六种运算符重载的方法和实现。

所谓运算符重载,也就是堆已有的运算符重新进行定义,赋予另一种功能,以适应不同的数据类型。

二. 加号运算符重载

        我们大家都知道普通的加法运算,例如我们从小就学习的1+1,是等于2的。这里我们的程序也能计算出来,但如果进行加法运算的两个对象不是两个整形数据,而是由自己定义的数据类型呢?这个时候编译器就无法得出计算结果,由此也就引出我们加号运算符的重载。

话不多说,我们直接来看进行了加号运算符重载的源代码:

#include<iostream>
using namespace std;
//实现加号运算符的重载

class Person {
public:
	Person(int num) {
		m_num = num;
	}
	
	Person& operator+(Person p1) {
		Person temp(0);
		temp.m_num = this->m_num + p1.m_num;
		return temp;
	}

	int m_num;
};

void test01() {
	Person p1(10);
	Person p2(20);
	Person p3 = p1.operator+(p2);
	cout << "p1= " << p1.m_num << endl;
	cout << "p2= " << p2.m_num << endl;
	cout << "p3= " << p3.m_num << endl;
}

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

如上代码所示,我们在Person类当中重载了运算符+号,使它能够实现两个我们自己定义的数据类型相加。最后值得注意的是,代码Person p3=p1.operator+(p2)其实就等价于p3=p1+p2;

 三. 左移运算符重载

        举个例子,由于左移运算符的输出结构类似于cout<<p<<endl; 这个时候,我们的cout就位于了<<的左侧,所以我们无法利用成员函数重载<<运算符,因为无法实现cout在左侧。

这个时候就只能利用全局函数重载。

在这里给大家拓展一个知识点,如果不了解某个专业术语或者名称的数据类型或结构,就可以点击鼠标右键,然后再次点击跳转到定义处,就能查询了。例如在此之前大家并不了解cout的数据类型,而我们在经过查询后就可以得出,cout为ostream数据类型。

下面我们来看下实现左移运算符重载的源代码:

#include<iostream>
using namespace std;
//实现左移运算符<<的函数重载

class Person {
public:
	int m_A;
	int m_B;
	Person() {
		m_A = 10;
		m_B = 23;
	}
	
};

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

void test01() {
	Person p1;
	cout << p1 << endl;
}

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

在对<<重载的函数中,为了能使cout<<p1后面能再接上请按任意键继续的界面,所以需要返回一个cout,而cout的数据类型为ostream,并且是引用类型的。

四.  递增运算符重载

        为了区分前置递增和后置递增,我们规定void operator++(int)为后置++运算符,其中的int代表占位参数。

#include<iostream>
using namespace std;

class MyInter{
public:
    MyInter(){
        m_age=0;
    }

    MyInter& operator++(){
        m_age++;
        return *this;
    }

    int operator++(int){
        int temp;
        temp=*this;
        m_age++;
        return temp;
    }

    int m_age;

}

void test01(){
    MyInter myinter;
    cout<<++myinter<<endl;
    cout<<myinter<<endl;
}

void test02(){
    MyInter myinter;
    cout<<myinter++<<endl;
    cout<<myinter<<endl;
}

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

如上述代码所示,test01测试函数测试了前置递增的结果,test02测试函数测试了后置递增的结果。值得注意的是后置递增的重载,返回值跟前置递增重载的返回值有很大区别。

五. 赋值运算符重载

        在赋值运算符中,如果不实现深拷贝,程序就会因为浅拷贝所带来的问题而导致整个程序崩溃。实现过程可概括为:先判断原来的堆区是否已经被释放,如果没有,则重新进行释放,然后再开辟一个新的空间。并且为了能进行连续赋值操作,我们需要在重载函数中返回这个本身,也就是*this

         

#include<iostream>
using namespace std;
//进行赋值运算符的重载


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

	~Person() {
		if (m_age != NULL) {
			delete m_age;
			m_age = NULL;
		}
	}

	Person& operator=(Person& p) {
		if (m_age != NULL) {
			delete m_age;
			m_age = NULL;
		}
		m_age = new int(*p.m_age);
		return *this;
	}

	int *m_age;
};

void test01() {
	Person p1(19);
	Person p2(20);
	p1 = p2;
	cout << "p1的年龄为:" << *p1.m_age << endl;
	cout << "p2的年龄为:" << *p2.m_age << endl;
}


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

六. 关系运算符重载

         值得注意的是,关系运算符重载函数的返回值为bool类型,因为返回的是true和false。

#include<iostream>
using namespace std;

class MyInter{
public:
    int m_a;
    int m_b;
    MyInter(int a,int b){
        m_a=a;
        m_b=b;
    }

    bool operator!=(MyInter myinter){
        if(m_a!=myinter.m_a&&m_b!=myinter.m_b){
            return true;
        }
        else{
            return false;
        }

}

void test01(){
    MyInter my1(10,20);
    MyInter my2(10,20);
    if(my1!=my2){
        cout<<"my1和my2是不相等的"<<endl;
    }
    else{
        cout<<"my1和my2是相等的"<<endl;
    }
}
int main()
{
    test01();
    return 0;
}

如上代码所示,我们进行关系运算符中不等于的重载,由于我们所定义的my1和my2里面的两个数据都是相同的,因此最后的输出结果也是两者相同的结果。

 七. 函数调用运算符重载

        在学习了上面五种运算符的重载之后,没想到我们的函数调用也是可以重载的吧。由于重载后的函数调用使用方式非常像函数的调用,因此我们也称为仿函数。仿函数没有固定写法,非常灵活。

拓展小知识:如果在这个过程中,我们不想要创建一个对象,那么就可以使用一个匿名对象来调用。

#include<iostream>
using namespace std;

class MyAdd {
public:
	int operator()(int v1,int v2){
		return v1 + v2;
	}
};


void test01() {
	MyAdd add;
	int ret=add(3, 4);
	cout << "ret= " << ret << endl;
	cout << "MyAdd()(100,100)= " << MyAdd()(100, 100) << endl;
}

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

如上述代码所示中,MyAdd()就是一个匿名函数的调用。 

;