运算符重载
来源:互联网 发布:雷军的编程能力 编辑:程序博客网 时间:2024/06/07 20:03
重载运算符可以把C++的运算符扩展到自定义类型和类类型的领域中,使代码更直观、易懂,方便、简洁。
说明:
目的:C++代码更直观,易读,使用更方便。
实质:运算符重载的实质是函数重载,只不过它重载的是类似“+ - * / =“ 这样的操作符。
实质:运算符重载的实质是函数重载,只不过它重载的是类似“+ - * / =“ 这样的操作符。
运算符重载的限制
a、重载运算符时,重载运算符的运算顺序和优先级不变。
b、不能创造新运算符
c、规定不能重载的运算符:. 类属关系运算符 .* 成员指针运算符 :: 作用域运算符 ?: 条件运算符 # 编译预处理符号 sizeof() 取数据类型的长度
b、不能创造新运算符
c、规定不能重载的运算符:. 类属关系运算符 .* 成员指针运算符 :: 作用域运算符 ?: 条件运算符 # 编译预处理符号 sizeof() 取数据类型的长度
运算符重载的语法
两种形式:
a、重载为类的成员函数
函数类型 operator 运算符(形参表)
{
函数体;
}
b、重载为类的友元函数
friend 函数类型 operator 运算符(形参表)
{
函数体;
}
a、重载为类的成员函数
函数类型 operator 运算符(形参表)
{
函数体;
}
b、重载为类的友元函数
friend 函数类型 operator 运算符(形参表)
{
函数体;
}
1.重载为类的成员函数:
一元运算符:++、-- 等
二元运算符:+、-、*、/、% 、=、+=、-=
二元运算符:+、-、*、/、% 、=、+=、-=
#include <iostream>#include <iomanip>using namespace std ;class complex{public: complex( double real = 0, double imag = 0): r( real),i( imag){} complex operator +( complex&); complex operator -( complex&); complex operator +=(complex &); void print() { cout << setiosflags(ios ::showpos ) << r << " " << i << 'i' << endl; }private: double r, i;};complex complex ::operator +(complex & c ) { return complex(r + c.r, i + c.i);}complex complex ::operator -(complex & c ) { return complex(r - c.r,i - c.i);}complex complex ::operator + =(complex & c ) { r += c.r; i += c.i; return *this;}void main () { complex c1(1,1), c2(3,3), c3; c3 = c1 + c2; // 复数相加 c3. print(); c3 = c1 - c2; // 复数相减 c3. print(); c3 += c2 += c1; //复数相加后赋值 c3. print();}
说明:
a.二元运算符
对象本身*t h is 就是其中的一个操作数,另一个操作数由形参给出,通过运算符重载的函数进行传递;
b.一元运算符
操作数由对象的this 指针给出,就不再需要形参了。
一般来说,运算结果的类型与操作数的类型一致
对象本身*t h is 就是其中的一个操作数,另一个操作数由形参给出,通过运算符重载的函数进行传递;
b.一元运算符
操作数由对象的this 指针给出,就不再需要形参了。
一般来说,运算结果的类型与操作数的类型一致
在重载复数“+=” 运算符时,return 语句中的表达式是*this ,而其他运算符函数的return 语句的表达式是一个临时对象complex(r-c.r,i-c.i)。其实,将return *this 改为返回一个临时对象return complex(r,i) 结果是一样的,只是建立临时对象还要调用构造函数。返回*this 对象就不需要调用构造函数了,执行效率可以提高。
2.重载为类的友元函数:
运算符也可以重载为友元函数,这时运算所需要的操作数都需要通过形参来传递,形参从左到右的顺序就是运算符操作数的顺序。
#include <iostream>#include <iomanip>using namespace std ;class complex{public: complex( double real=0, double imag=0): r( real),i( imag){} friend complex operator+( complex&, complex&); friend complex operator -( complex&, complex&); friend complex& operator +=(complex &,complex &); void print() { cout<< setiosflags(ios ::showpos ) <<r<< " "<<i<<'i' <<endl ; }private: double r, i;};complex operator +(complex & c1 ,complex & c2 ){ return complex( c1.r + c2.r, c1.i + c2.i);}complex operator -(complex & c1 ,complex & c2 ){ return complex( c1.r - c2.r, c1.i - c2.i);}complex& operator + =(complex & c1 ,complex & c2 ) { c1.r += c2.r; c1.i += c2.i; return c1;}void main () { complex c1(1,1), c2(3,3), c3; c3 = c1 + c2; // 复数相加 c3. print(); c3 = c1 - c2; // 复数相减 c3. print(); c3 += c2 += c1; //复数相加后赋值 c3. print();}
说明:
重载为友元函数,比如“+” ,操作数都由形参给出,通过运算符重载的函数进行传递。并且运算结果的类型与操作数的类型一致。
重载为友元函数,比如“+” ,操作数都由形参给出,通过运算符重载的函数进行传递。并且运算结果的类型与操作数的类型一致。
重载运算符的操作中,无论重载为成员函数还是友元函数,其形参多为引用类型,目的是增加可读性,提高程序的运行效率,因为使用引用类型,在进行参数传递的过程中,不需要复制临时对象。
重载++和--运算符
在C++ 中有一类特殊的运算符,“++”、“--”运算符,这类运算符是一元运算符,它的运算规律因操作数的位置不同而不同。
++x :前置自增算符,先自身增1 ,再将增加后的值作为表达式的值返回;
x++ :后置自增算符,先将本身的值作为表达式的值返回,自身再增1。
++x :前置自增算符,先自身增1 ,再将增加后的值作为表达式的值返回;
x++ :后置自增算符,先将本身的值作为表达式的值返回,自身再增1。
#include <iostream>using namespace std ;class weight{public: weight( int v=0) : value( v) {} // 前置自增 weight& operator ++(); // 后置自增 weight operator ++(int ); void print() { cout << value << endl; }private: int value;};// 前增量weight& weight ::operator ++(){ value++; return * this;}// 后增量weight weight ::operator ++(int ){ weight temp(* this); //操作数保存为临时对象 value++; // 操作数加1 return temp; // 返回没有加1的临时对象}void main (){ weight s1(1); s1++. print(); //1 s1. print(); //2 (++ s1). print(); //3}
说明:
因为重载函数只能从形式参数上加以区别。
1、前置自增运算符
用成员函数实现时,没有形式参数。
2、后置自增运算符
另外增加一个形式上的形式参数,类型定为int。这个参数只是用来区别两种自增算符,并不参加实际的运算。
因为重载函数只能从形式参数上加以区别。
1、前置自增运算符
用成员函数实现时,没有形式参数。
2、后置自增运算符
另外增加一个形式上的形式参数,类型定为int。这个参数只是用来区别两种自增算符,并不参加实际的运算。
#include <iostream>using namespace std ;class weight{public: weight( int v=0):value( v){} friend weight& operator ++(weight &); friend weight operator ++(weight &,int ); void print() { cout<<value<< endl; }private: int value;};weight& operator + +(weight & s ){ s.value++; return s;}weight operator + +(weight & s ,int ){ weight temp( s); s.value++; return temp;}void main (){ weight s1(1); s1++. print(); //1 s1. print(); //2 (++ s1). print(); //3}
重载赋值运算符
在C++ 中系统提供一个默认的重载的赋值运算符,所以同类的对象可以互相赋值。
缺省=运算符 和 缺省拷贝构造函数功能完全相同。
缺省=运算符 和 缺省拷贝构造函数功能完全相同。
例如:
RMB r1(20.3), r2;
RMB r3 = r1;
r2 = r1;
创建对象r3,调用的是拷贝构造函数,即用已有的对象创建新对象。
r2 在赋值运算表达式中,对象已经存在,使用“=” 为对象赋值,调用的是赋值运算符。
RMB r1(20.3), r2;
RMB r3 = r1;
r2 = r1;
创建对象r3,调用的是拷贝构造函数,即用已有的对象创建新对象。
r2 在赋值运算表达式中,对象已经存在,使用“=” 为对象赋值,调用的是赋值运算符。
一般来说,这个重载的赋值运算符可以直接使用,不需要自己定义。但是,在有些情况下,比如动态申请对内存的情况,则还是需要自己定义重载的赋值运算符。
#include <iostream>using namespace std ;class Name{public: Name( char *str= NULL); Name( Name &s); Name& operator = ( Name&); ~Name() { delete pName; } void print() { cout<<pName<< endl; }private: char *pName;};Name::Name (char *str ) { if( str== NULL) pName = NULL; else{ pName= new char[ strlen( str)+1]; strcpy(pName, str); }}Name& Name ::operator = (Name & s ){ if( this == & s) //需要判断其是否相等 return * this; delete pName; pName= new char[ strlen( s.pName)+1]; strcpy(pName, s.pName); return * this; }Name::Name (Name &s ){ pName= new char[ strlen( s.pName)+1]; strcpy(pName, s.pName);}void main (){ Name s1( "test = operator"),s2 ; s2 = s1; s2. print();}
说明:
由于在类的构造过程中动态申请了对内存,因此必须重载拷贝构造函数和赋值运算符。
a.拷贝构造函数在创建对象时调用,因为此时对象还不存在,只需要申请新的空间,而不需要释放原有资源空间。
b.赋值运算符在对象已存在的条件下调用,因此需要先释放原对象占用的空间,然后申请新的空间。
由于在类的构造过程中动态申请了对内存,因此必须重载拷贝构造函数和赋值运算符。
a.拷贝构造函数在创建对象时调用,因为此时对象还不存在,只需要申请新的空间,而不需要释放原有资源空间。
b.赋值运算符在对象已存在的条件下调用,因此需要先释放原对象占用的空间,然后申请新的空间。
重载转换运算符
在C++ 中,数据类型转换对于基本数据类型有两种方式:隐式数据类转换 和 显式数据类型转换,也叫强制类型转换
对于自定义类型和类类型,类型转换操作是没有定义的。
强制类型转换使用“( )” 运算符完成,在C++ 中我们可以将“( )” 运算符进行重载,达到数据转换的目的。
对于自定义类型和类类型,类型转换操作是没有定义的。
强制类型转换使用“( )” 运算符完成,在C++ 中我们可以将“( )” 运算符进行重载,达到数据转换的目的。
转换运算符声明形式
operator 类型名 ();
特点:a.没有返回值 b.功能类似强制转换
operator 类型名 ();
特点:a.没有返回值 b.功能类似强制转换
#include <iostream>using namespace std ;class RMB{public: RMB( double value = 0.0) { yuan = value; fen = ( value - yuan) * 100 + 0.5; } void ShowRMB() { cout<<yuan<< "元" <<fen<< "分" <<endl ; } operator double () { return yuan + fen / 100.0; }private: int yuan, fen;};void main (){ RMB r1(1.01), r2(2.20); RMB r3; // 显式转换类型 r3 = RMB(( double) r1 + ( double) r2); r3. ShowRMB(); // 3元21分 // 自动转换类型 r3 = r1 + 2.40; r3. ShowRMB(); // 3元41分 // 自动转换类型 r3 = 2.0 - r1; r3. ShowRMB(); // 0元99分}
对于r3=r1+2.40; 的系统工作:a.寻找重载的成员函数+运算符 b.寻找重载的友元函数+运算符 c.寻找转换运算符 d.验证转换后的类型是否支持+运算。
转换运算符重载一般建议尽量少使用。
转换运算符重载一般建议尽量少使用。
小结:
1.注意运算符重载的规则和限制
2.重载运算符的时候要注意函数的返回类型
2.前增量和后增量运算符的重载区别
4.赋值运算符重载要注意内存空间的释放和重新申请
5.转换运算符重载与构造函数、析构函数一样没有返回值,通过转换运算符重载可以在表达式中使用不同类型的对象,但要注意转换运算符重载不可滥用。
1.注意运算符重载的规则和限制
2.重载运算符的时候要注意函数的返回类型
2.前增量和后增量运算符的重载区别
4.赋值运算符重载要注意内存空间的释放和重新申请
5.转换运算符重载与构造函数、析构函数一样没有返回值,通过转换运算符重载可以在表达式中使用不同类型的对象,但要注意转换运算符重载不可滥用。
- 运算符重载 [++,--,+,<<; &&,||(不可重载)]
- 重载之运算符重载
- 重载赋值运算符
- C++运算符重载
- 运算符重载
- 运算符重载总结
- 运算符重载例子
- 运算符重载
- 运算符重载
- 基础:运算符重载
- 运算符重载
- 运算符重载
- 重载赋值运算符
- C#运算符重载
- C++-运算符重载
- 重载赋值运算符
- 运算符重载
- 有关运算符重载
- 如何将 SQL SERVER 彻底卸载干净
- No result defined for action com.web.action.UserAction and result input
- ps切图:png8和png24的区别
- 利用ffmpeg做视频解码的顺序
- 问:当前计算机系统一般会采用层次结构存储数据,请介绍下典型计算机存储系统一般分为哪几个层次,为什么采用分层存储数据能有效提高程序的执行效率?
- 运算符重载
- 关于C++和C中字符串的几点说明
- 使用clone解决hibernate+spring集成中的延迟加载问题及分析(no session or session was closed)
- ZOJ:3365 Integer Numbers
- COJ 1223 JAVA入门训练modpow
- 腾讯14研发笔试回忆
- NYOJ 题目854 留恋
- JavaScript对象和数组
- 继承与派生