目录
1. 运算符重载
1.1 概念
C++中可以把部分运算符看做成函数,此时运算符也可以重载。
运算符预定义的操作只能针对基本数据类型,但是对于自定义类型,也需要类似的运算操作,此时就可以重新定义这些运算符的功能,使其支持特定类型,完成特定的操作。
如果不做特殊处理,C++ 的 +、-、*、/ 等运算符只能用于对基本类型的常量或变量进行运算,不能用于对象之间的运算。类的对象中有很多个成员变量,运算符不知道对哪个成员变量进行运算,这时候就需要对运算符进行重载,让运算符明确知道要对哪个成员变量进行运算。
其实相当于定义一个函数来进行特定的运算。
运算符重载有两种实现方式:
● 友元函数运算符重载
● 成员函数运算符重载
1.2 友元函数运算符重载
(1)在类内声明实现运算符重载功能的友元函数名称
(2)在类外定义函数体定义函数实现运算符重载功能
友元函数实现运算符重载实例:
注意:当自增运算符进行重载时,前置自增 ++i 与后置自增i++的函数名字一样,但是参数不一样,通过函数重载进行区分。
如果是 前置自增 ++i , 参数只有一个进行自增的变量。
如果是后置自增 i++,参数除了进行自增的变量,还需要加一个哑元参数。
// 友元函数 ++运算符重载声明
// 利用参数不同,进行函数重载
friend Myint operator ++(Myint &i); // 前置++
friend Myint operator ++(Myint &i,int); // 后置++
#include <iostream>
using namespace std;
class Myint
{
private:
int a;
public:
Myint(int a):a(a){}
int get_int()
{
return a;
}
// 友元函数 +运算符重载声明
friend Myint operator +(Myint &a,Myint &b);
// 友元函数 -运算符重载声明
friend Myint operator -(Myint &a,Myint &b);
// 友元函数 ++运算符重载声明
// 利用参数不同,进行函数重载
friend Myint operator ++(Myint &i); // 前置++
friend Myint operator ++(Myint &i,int); // 后置++
};
//加法重载
Myint operator +(Myint &i,Myint &j)
{
// Myint int4(0);
// int4.a = i.a + j.a;
// return int4;
return i.a + j.a;
}
//减法重载
Myint operator -(Myint &i,Myint &j)
{
Myint int4(0);
int4.a = i.a - j.a;
return int4;
}
// 前置++
Myint operator ++(Myint &i)
{
// Myint int4(0);
// ++int4.a
// return int4;
return ++i.a;
}
// 后置++
Myint operator ++(Myint &i,int)
{
// Myint int4(0);
// int4.a = i.a++;
// return int4;
return i.a++;
}
int main()
{
Myint int1(2);
Myint int2(int1); // 拷贝构造函数
cout << int2.get_int() << endl;
cout << endl;
cout << "加法重载:" << endl;
Myint int3 = int1 + int2;
cout << int3.get_int() << endl;
cout << endl;
cout << "减法重载:" << endl;
Myint int5 = int1 - int2;
cout << int5.get_int() << endl;
cout << endl;
cout << "后置自增:" << endl;
cout << (int3++).get_int() << endl; // 后置自增
cout << int3.get_int() << endl;
cout << endl;
Myint int6 = int3++;
cout << int6.get_int() << endl;
cout << endl;
cout << "前置自增:" << endl;
cout << (++int3).get_int() << endl; // 前置自增
cout << int3.get_int() << endl;
cout << endl;
Myint int7 = ++int3;
cout << int7.get_int() << endl;
return 0;
}
1.3 成员函数运算符重载
成员函数运算符重载相比于友元函数重载,最主要的区别是,友元函数的第一个输入参数,在成员函数运算符重载使用this指针代替,因此同样的运算符重载,成员函数运算符重载比友元函数运算符重载参数少一个。
成员函数进行运算符重载实例:
因为进行自增的变量已经进行由this指针代替,所以前置自增为无参函数,后置自增只需要写哑元参数即可。
// 成员函数 ++运算符重载声明
Myint operator ++(); // 前置++
Myint operator ++(int); // 后置++
#include <iostream>
using namespace std;
class Myint
{
private:
int a;
public:
Myint(int a):a(a){}
int get_int()
{
return a;
}
// 成员函数 +运算符重载声明
Myint operator +(Myint &i);
// 成员函数 -运算符重载声明
Myint operator -(Myint &i);
// 成员函数 ++运算符重载声明
Myint operator ++(); // 前置++
Myint operator ++(int); // 后置++
};
//加法重载
Myint Myint::operator +(Myint &i)
{
return this->a + i.a;
}
//减法重载
Myint Myint::operator -(Myint &i)
{
return this->a - i.a;
}
// 前置++
Myint Myint::operator ++()
{
return ++this->a;
}
// 后置++
Myint Myint::operator ++(int)
{
return this->a++;
}
int main()
{
Myint int1(2);
Myint int2(int1); // 拷贝构造函数
cout << int2.get_int() << endl;
cout << endl;
cout << "加法重载:" << endl;
Myint int3 = int1 + int2;
cout << int3.get_int() << endl;
cout << endl;
cout << "减法重载:" << endl;
Myint int5 = int1 - int2;
cout << int5.get_int() << endl;
cout << endl;
cout << "后置自增:" << endl;
cout << (int3++).get_int() << endl; // 后置自增
cout << int3.get_int() << endl;
cout << endl;
Myint int6 = int3++;
cout << int6.get_int() << endl;
cout << endl;
cout << "前置自增:" << endl;
cout << (++int3).get_int() << endl; // 前置自增
cout << int3.get_int() << endl;
cout << endl;
Myint int7 = ++int3;
cout << int7.get_int() << endl;
return 0;
}
1.4 赋值运算符重载
除了之前学习的无参构造函数、拷贝构造函数和析构函数以外,如果程序员不手写,编译还会给一个类添加赋值运算符重载函数。
赋值运算符=
要求左右两个操作数的类型是匹配的,或至少是兼容的。有时希望=
两边的操作数的类型即使不兼容也能够成立,这就需要对=
进行重载。
C++规定,=
赋值运算符重载只能使用成员函数运算符重载。
赋值运算符重载实例:
int2 = int1; 当进行这句赋值操作时,就需要利用赋值运算符重载。
#include <iostream>
using namespace std;
class MyInt
{
private:
int a;
public:
MyInt(int a):a(a){}
int get_int()
{
return a;
}
MyInt& operator=(MyInt &i)
{
// 编译器自动添加的运算符重载不会打印这句话
cout << "赋值运算符重载被调用了" << endl;
this->a = i.a;
return *this;
}
};
int main()
{
cout << "Hello World!" << endl;
MyInt int1(2);
MyInt int2(4);
cout << int1.get_int() << endl;
cout << int2.get_int() << endl;
cout << endl;
int2 = int1;
cout << int1.get_int() << endl;
cout << int2.get_int() << endl;
return 0;
}
1.5 类型转换运算符重载
在 C++ 中,类型的名字(包括类的名字)本身也是一种运算符,即类型强制转换运算符。
类型强制转换运算符是单目运算符,也可以被重载,但只能重载为成员函数,不能重载为全局函数。
经过适当重载后,(类型名)对象
这个对对象进行强制类型转换的表达式就等价于对象.operator 类型名()
,即变成对运算符函数的调用。
必须使用成员函数运算符重载,并且格式比较特殊。
类型转换运算符重载实例:
int a= int1; 运行这一句的时候,把对象中的int类型的成员函数给 变量 int a
string b = int1; 运行这一句的时候,把对象中的srtring类型的成员变量 给 strng b
#include <iostream>
using namespace std;
class MyInt
{
private:
int a;
string str = "hello";
public:
MyInt(int a,string b):a(a),str(b){}
int get_int()
{
return a;
}
operator int()
{
return a;
}
operator string()
{
return str;
}
};
int main()
{
cout << "Hello World!" << endl;
MyInt int1(2,"world");
int a= int1;
cout << "a=" << a << endl;
cout << endl;
string b = int1;
cout << "b=" << b << endl;
cout << endl;
return 0;
}
1.6 注意事项
● 重载的运算符限制在C++语言中已有的运算符范围,不能创建新的运算符。
● 运算符重载本质上也是函数重载,但是不支持函数参数默认值。
● 重载之后的运算符不能改变运算符的优先级和结合性,也不能改变运算符的操作数和语法结构。
● 运算符重载必须基于或者包含自定义类型,即不能改变基本数据类型的运算规则。
● 重载的功能应该与原有的功能相似,避免没有目的的滥用运算符重载。
● 一般情况下,双目运算符建议使用友元函数运算符重载,单目运算符建议使用成员函数运算符重载。