很多小伙伴会想知道c++是如何重载运算符的,那让我们来看看下面的代码。
之前已对多态性有了相关总结,得出结论:函数重载体现出多态性。实际上,运算符重载也体现出了多态性。在C++中我们定义的int、float、double等基本数据类型的变量后,就可以直接用“ + ”、“ - ”、“ * ”、“ / ”等运算符进行相关的计算,然后把得到的 计算 结果通过" cout<< "输出结果。但有没有想过为什么可以用“ + ”、“ - ”、“ * ”、“ / ”等运算符进行相关的计算就可以得到我 们想要的结果?中间的运算过程是谁定义的?
其实,这是编译程序帮我们完成了中间的运算过程,正是因为有了针对预定义的基本数据类型的运算符重载才给我们编程带来很多方便。但是如果我们把自己定义的数据类型(如自己定义的类)的变量进行算,那C++预定义的基本数据类型的运算符重载将不再适合我们使用,这时我们需要自行重载运算符。
下面是 + 在类里面的函数重载和全局范围的重载,在成员函数里面的重载,读者可自己推一下,后面只写全局范围的重载,加减乘除大致相同,重载成什么样取决与操作者。
1. +号重载 (“ + ”、“ - ”、“ * ”、“ / ”与此类似)
#include<iostream>
#include<string>
using namespace std;
//在这里我们先创建一个对象
class Person {
public:
int m_a;
int m_b;
//成员函数重载
/*person operator + (person & p) {
person temp;
temp.m_a = this->m_a + p.m_a;
temp.m_b = this->m_b + p.m_b;
return temp;
}*/
};
//全局函数重载,要写在类的下面,在vs2022下好像会报错
//加号运算符重载
Person operator+(Person& p1, Person& p2) {
Person temp;
temp.m_a = p1.m_a + p2.m_a + 1;
temp.m_b = p1.m_b + p2.m_b;
return temp;
}
void test01() {
Person p1;
p1.m_a = 10;
p1.m_b = 10;
Person p2;
p2.m_a = 10;
p2.m_b = 10;
Person p3 = p1 + p2;
cout << p3.m_a << endl;
cout << p3.m_b << endl;
}
int main()
{
test01();
}
2.左移运算符的重载(全局范围下)
ostream& operator<<(ostream& cout, Person& p)
{
cout << "m_a= " << p.m_a << "m_b= " << p.m_b;
return cout;
}
void test02() {
Person p;
p.m_a = 10;
p.m_b = 10;
cout << p<<endl;
}
这里之所以用&是为了模仿<<,不加的话可能不能连续输出;
3.++运算的重载(--与此类似)
#include<iostream>
#include<string>
using namespace std;
class MYint {
//声明为友元
friend ostream& operator<<(ostream& cout, MYint myint);
public:
MYint()
{
m_num = 0;
}
//重载前置++运算符
MYint& operator++()
{
//先进行++运算
m_num++;
//再将自身返回
return *this;
}
//重载后置++运算符
MYint operator++(int) //int 占位参数 且只能是int;可以区分前置和后置
{
//先记录当时的结果
MYint temp = *this;
m_num++;
//最后将记录结果返回
return temp;
}
private:
int m_num;
};
ostream& operator<<(ostream& cout, MYint myint) {
cout << myint.m_num;
return cout;
}
void test01()
{
MYint myint;
cout <<++myint << endl;
}
int main()
{
test01();
}
4.赋值运算符重载
#include<iostream>
#include<string>
using namespace std;
class Person {
public:
Person(int age)
{
m_age = new int(age);
}
int* m_age;
~Person()
{
if (m_age != NULL)
{
delete m_age;
m_age = NULL;
}
}
Person& operator=(Person& p)
{
//编译器提供的是浅拷贝
//M_age=p.m_age;
//应该先判断是否有属性在堆区,如果有先释放干净,然后再深拷贝
if (m_age != NULL)
{
delete m_age;
m_age = NULL;
}
//深拷贝
m_age = new int(*p.m_age);
//返回对象本身
return *this;
}
};
void test01()
{
Person p1(18);
Person p2(20);
// 程序崩溃 堆区内存重复释放 浅拷贝所带来的问题当没有重载的时候
Person p3=p2 = p1;//赋值操作 但此处容易存在问题简单的拷贝 p1和p2指向的是同一块内存
cout << "p1的年龄: " << *p1.m_age << endl;
cout << "p2的年龄为:" << *p2.m_age << endl;
cout << "p3的年龄为:" << *p3.m_age << endl;
}
int main()
{
int a = 1;
int b = 2;
int c = 3;
c = a = b;
cout << "a= " << a << endl;
cout << "b= " << b << endl;
cout << "c= " << c << endl;
test01();
}
5.函数运算符重载
#include<iostream>
using namespace std;
//打印输出类运算符重载
class Myprint {
public:
//重载函数调用运算符
void operator()(string test)
{
cout << test << endl;
}
};
void test01()
{
Myprint myPrint;
myPrint("hello world"); //由于使用起来非常向函数,所以叫防函数
}
//仿函数非常灵活没有固定的写法;
class Myadd {
public:
int operator()(int num1, int num2)
{
return num1 + num2;
}
};
void test02()
{
Myadd madd;
int ret=madd(2, 4);
cout << "ret= " << ret << endl;
//匿名函数对象
cout << Myadd()(100, 100) << endl;
}
int main()
{
test01();
test02();
}