运算符重载
运算符重载的概念
在C++中,基本的算数运算符,如果不做特殊处理,则 不能用于对象之间的运算 。
运算符重载的目的:使得C++中的运算符也能够 用来操作对象 。
用于类运算的运算符通常都要重载。有两个运算符,系统提供了默认的重载版本:赋值运算符 =
和 地址运算符 $
与其他函数一样,重载运算符有一个返回类型和一个参数列表。这样的函数被称为 运算符函数 。
运算符可以被重载为 全局函数 ,也可以被重载为 类的成员函数 。
声明为全局函数时,通常应是 类的友元 。
运算符函数是一种特殊的 友元函数 或 全局函数 。
不可重载的运算符和符号
名称 | |
---|---|
成员访问运算符 | . |
成员指针访问运算符 |
. * 、-> *
|
域运算符 | :: |
长度运算符 | sizeof |
条件运算符 | ?: |
预处理符号 | # |
重载运算符的规则
- 重载后的运算符的含义应该 符合原有的用法习惯 ;
- 运算符重载 不能改变 运算符原有的含义;
- 运算符重载 不能改变 运算符操作数的个数及语法结构;
- 运算符重载 不能改变 运算符用于基本数据类型对象的含义;
- 不能创建新的运算符;
- 重载运算符
()
、[]
、->
、=
时,只能将它们重载为 成员函数 ,不能重载为全局函数。
重载运算符为类的成员函数
定义和声明:
class 类名
{
private:
类型 成员变量;
public:
类型 opeartor 运算符 (参数列表);
};
类型 类名::opeartor 运算符 (参数列表)
{
函数体
};
运算符执行时,C++编译器解析:
对象名.opeartor 运算符 (参数列表);
重载运算符为友元函数
定义和声明:
class 类名
{
private:
类型 成员变量;
public:
friend 类型 opeartor 运算符 (参数列表);
};
类型 opeartor 运算符 (参数列表)
{
函数体
};
运算符执行时,C++编译器解析:
opeartor 运算符 (参数列表);
重载赋值运算符
C++规定,赋值运算符 =
只能被重载为成员函数。
若有类CL的两个对象s1和s2,则它们之间的赋值语句通常是下面的形式:
s1 = s2;
当类CL重载了赋值运算符后,则上述语句被解释为 函数调用 的形式:
s1.opeartor=(s2);
浅拷贝和深拷贝
同类对象之间可以通过赋值运算符 =
互相赋值。如果没有经过重载,=
的作用就是将赋值号右侧对象的值一一赋值给左侧的对象 。这相当于值的拷贝,称为 浅拷贝 。
重载赋值运算符后,赋值语句的功能是将 一个对象中指针成员变量指向的内容复制到另一个对象中指针成员变量指向的地方 ,这样的拷贝叫做 深拷贝 。
重载流插入运算符和流提取运算符
必须重载为友元函数 。
#include <iostream>
using namespace std;
class Test
{
private:
int a;
int b;
public:
friend ostream & opeartor<< (ostream &, Test);
friend istream & opeartor>> (istream &, Test);
};
ostream & opeartor<< (ostream & o_stream, Test obj)
{
o_stream << obj.a << endl;
o_stream << obj.b << endl;
return o_stream;
}
istream & opeartor>> (istream & i_stream, Test obj)
{
i_stream >> obj.a;
i_stream >> obj.b;
return i_stream;
}
重载自增、自减运算符
按照自增、自减运算符的本来定义,++obj
的返回值应该是 obj被修改后的值 ,而 obj++
的返回值应该是 obj被修改前的值 。
class 类名
{
private:
int i;
public:
// 成员函数 - 前置形式
类型 opeartor ++ ();
// 成员函数 - 后置形式
类型 opeartor ++ (int);
// 友元函数 - 前置形式
friend 类型 opeartor -- (类名引用);
// 友元函数 - 后置形式
friend 类型 opeartor -- (类名引用, int);
};
类型 类名::opeartor ++ () {};
类型 类名::opeartor ++ (int) {};
类型 opeartor -- (类名引用) {};
类型 opeartor -- (类名引用, int) {};
重载强制类型转换运算符
强制类型转换运算符是单目运算符,也可以被重载, 但只能重载为成员函数 。
class 类名
{
private:
类型 成员变量;
public:
opeartor 类型名 ();
};
经过适当的重载后,(类型名)对象;
转换为 对象.opeartor 类型名 ();