
运算符重载.ppt
50页第六章 运算符重载,,引言,运算符和函数,4=1 + 3,4.0=1.0 + 3.0,函数名,参数int,返回值int,函数名,参数double,返回值double,,,,,,,,,int + (int, int );,double + (double, double );,可以将+代表的操作看成一个函数:+为函数的名字,+操作的两个操作数的类型即为函数形参的类型,+操作的结果的类型即为函数的返回值类型引言,运算符重载的提出,C/C++中,每种基本数据类型的变量都可通过几种运算符来做相关计算,如int型变量,它们可以同“+”,“-”,“*”,“/”等运算符来做加法,减法,乘法,除法等如:,int a, b;a+b; a-b; a*b; a/b;,class Vector{int * data;int num;public: … …},我们能否将自定义的类的对象也通过“+”,“-”,“*”,“/”等运算符来进行两个对象的加,减,乘,除呢?如:,Vector vec1,vec2;vec1+vec2; vec1-vec2; vec1*vec2; vec1/vec2;,定义一个向量类,两个向量类对象的加减乘除,C++提供了运算符重载机制来帮助我们实现上述目的。
主要内容,6.1 基本语法6.2 常用运算符的重载6.3 赋值运算符的重载6.4 输入输出运算符的重载6.5 []运算符的重载6.6 用户自定义类型转换,6.1 基本语法,在C++ 中,为一个类类型定义运算符函数和定义普通函数的形式很相似,只是函数的名字是关键字operator后紧跟要重载的运算符例如,重载的”+” 运算符函数名字为operator+定义了运算符函数之后,就可以对类类型的操作数使用该运算符运算符函数声明的语法规则如下:,friend 类型名 operator运算符(形参列表);,friend 关键字可选,有friend关键字时表示运算符函数是类的友元函数,没有friend关键字时表示运输符函数是类的成员函数或普通函数6.1 基本语法,运算符函数声明的语法规则如下:,friend 类型名 operator运算符(形参列表);,形式列表中参数的个数取决于两个因素:,运算符是一元运算符还是二元运算符运算符函数是成员函数还是友元函数,6.1 基本语法,C++中内被重载的运算符有:,C++中不能被重载的运算符有:,6.1 基本语法,注意事项,虽然运算符重载提供了语法上的方便,但也有一些使用限制。
只有C++预定义运算符集合中的运算符才可以重载 C++中有些运算符不能被重载:::(作用域解析符)、.(成员选择符)、.*(成员指针间接引用符)及?:(条件运算符)不能定义C++中没有的运算符,如operator**会产生编译错误6.1 基本语法,注意事项,内置类型的运算符的预定义意义不能改变,也不能为内置数据类型定义其他运算符例如,不能定义内置数组的operator+重载运算符不能改变运算符的优先级和结合性重载运算符不能改变操作数的个数运算符重载不能滥用,只有当用户自定义类型上的操作与内置运算符之间存在逻辑对应关系时,重载的运算符才能使程序显得更自然、更直观6.2 常用运算符的重载,一元运算符的重载,本节给出一些常规运算符以成员函数和友元函数两种方式重载的例子在下面的代码中,我们分别以两个类Byte和Integer来举例说明如何使用成员函数和友元函数重载常用的运算符class Byte{ unsigned char b;public: Byte(unsigned char bb = 0) : b(bb){}};,class Integer { long i;public: Integer(long ll = 0) : i(ll) {}};,6.2 常用运算符的重载,一元运算符的重载(成员函数形式),class Byte { unsigned char b;public: Byte(unsigned char bb = 0) : b(bb) {} // 无副作用的运算符定义为 const成员函数 const Byte& operator+() const {//正号 return *this;} const Byte operator-() const {//负号 return Byte(-b);} const Byte operator~() const {//按位取反 return Byte(~b);} Byte operator!() const {//逻辑非 return Byte(!b);} Byte* operator&() {//取地址 return this;},一元运算符函数是成员函数时,形式参数列表里没有参数。
6.2 常用运算符的重载,一元运算符重载(成员函数形式),// 有副作用的运算符定义为非const成员函数 const Byte& operator++() { // 前缀++ b++; return *this;} const Byte operator++(int) { // 后缀++ Byte before(b); b++; return before;} const Byte& operator--() { // 前缀-- --b; return *this;} const Byte operator--(int) { // 后缀-- Byte before(b); --b; return before;}};,自增和自减运算符有前缀和后缀两种形式,都会改变对象,所以不能对常量对象操作前缀形式返回改变后的对象,返回*this后缀形式返回改变之前的值,所以必须创建一个代表这个值的独立对象并返回它,是通过传值方式返回的6.2 常用运算符的重载,一元运算符重载(成员函数形式),// 重载运算符的使用示例int main() { Byte b; +b; //b.operator+(); -b; //b.operator-(); ~b; //b.operator~(); Byte* bp = &b; //Byte* bp = b.operator&(); !b; //b.operator!(); ++b; //b.operator++(); b++; //b.operator++(int); --b; //b.operator--(); b--; //b.operator--(int);} //end of main(),运算符函数的调用有两种形式隐式调用和显式调用。
隐式调用,,程序在执行时实际调用Byte::operator@(&b);@为左侧main函数中的一元运算符一元运算符重载(friend函数形式),// 全局函数重载一元运算符,要带一个参数作为操作数//全局运算符函数一般要声明为类的友元class Integer { long i;public: Integer(long ll = 0) : i(ll) {} // 无副作用的运算符参数为 const& friend const Integer& operator+(const Integer& a); friend const Integer operator-(const Integer& a); friend const Integer operator~(const Integer& a); friend Integer* operator&(Integer& a); friend int operator!(const Integer& a); // 有副作用的运算符参数为非const引用 friend const Integer& operator++(Integer& a); // 前缀++ friend const Integer operator++(Integer& a, int);//后缀++ friend const Integer& operator--(Integer& a); // 前缀++ friend const Integer operator--(Integer& a, int);//后缀++}; //end of class Integer,一元运算符函数是友员函数或普通函数时,形式参数列表里有一个参数。
一元运算符重载(friend函数形式,// 全局运算符函数的定义const Integer& operator+(const Integer& a) { return a;}const Integer operator-(const Integer& a) { return Integer(-a.i);}const Integer operator~(const Integer& a) { return Integer(~a.i);}Integer* operator&(Integer& a) { return a.This(); // 不能用&a,会导致递归调用本函数}int operator!(const Integer& a) { return !a.i;},一元运算符重载(friend函数形式,// 前缀,返回增加后的对象const Integer& operator++(Integer& a) { a.i++; return a;}// 后缀,返回增加以前的对象值const Integer operator++(Integer& a, int) { Integer before(a.i); a.i++; return before;}const Integer& operator--(Integer& a) { a.i--; return a;}const Integer operator--(Integer& a, int) { Integer before(a.i); a.i--; return before;},自增和自减运算符有前缀和后缀两种形式,都会改变对象,所以不能对常量对象操作。
前缀形式返回改变后的对象,返回*this后缀形式返回改变之前的值,所以必须创建一个代表这个值的独立对象并返回它,是通过传值方式返回的一元运算符重载(friend函数形式,// 重载运算符的使用int main() { Integer a; +a; -a; ~a; Integer* ip = &a; !a; ++a; a++; --a; a--;}//end of main,程序在执行时调用operator@(a);@为左侧main函数中的一元运算符6.2 常用运算符重载,二元运算符重载(成员函数方式),class Byte { unsigned char b;public: Byte(unsigned char bb = 0) : b(bb) {} const Byte operator+(const Byte& right) const { return Byte(b + right.b);} const Byte operator-(const Byte& right) const { return Byte(b - right.b);} const Byte operator*(const Byte& right) const { return Byte(b * right.b);} const Byte operator/(const Byte& right) const { assert(right.b != 0); return Byte(b / right.b);} const Byte operator%(const Byte& right) const { assert(right.b != 0); return Byte(b % right.b);},。












