十三算符函数重载与流输入输出操作_第1页
十三算符函数重载与流输入输出操作_第2页
十三算符函数重载与流输入输出操作_第3页
十三算符函数重载与流输入输出操作_第4页
十三算符函数重载与流输入输出操作_第5页
已阅读5页,还剩11页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、十三算符函数重载与流输入输出操作算符函数重载(Operator Overloading)算符函数重载的声明C+语言中允许部分运算符号充当函数名从而构成算符函数。但算符函数的重载与普通函数的重载有一定的区别。算符函数重载的声明格式是:类型 operator C+语言支持的算符(参数描述表) ;例:# include < stdio.h >class Complex double r, i ; public: Complex (double rs = 0.,double is=0.) r = rs ; i = is; Complex operator+(const Complex &a

2、mp;add_2)return Complex(r+add_2.r, i + add_2.i); Complex operator-(const Complex &sub_2)return Complex(r-sub_2.r, i - sub_2.i);void operator!();void Complex:operator!() if (i>=0) printf (“% .2f + % .2fin”,r,i); else printf(“% .2f % .2fin”,r,i);void main() Complex a(3.,9.),b(7.,8.),c(0.,0.); c

3、=a.operator+(b);/当执行完此表达式后将执行析构函数 printf(“a+b =”); !c;-(a); printf (“b-a=”); !c;引用重载算符函数的简化·取消关键词“operator”、对象连接符号和括号; ·按原算符语意重组操作数(常)变量与算符的位置;按上述两条准则,则上例中的表达式“c= a.operator+(b);”便可改写为:“c= a +b;”。其余的可类推。推论:已知有:“A& operator+(A&);”的声明和class A 的对象a、b、c,则“a.operator(b.operator(c);”可简化为

4、:“a+b+c;”。再考虑:“a+b+c+10”应如何分解?使用算符函数重载的限制·只能使用C+算符的大部分,对“=、()、->”算符限制使用,对诸如“ sizeof、*、”等算符是禁止使用的。·不得改变原算符的语意(元数和位置);例:#include<iostream.h>class Aint i;public:A(int x):i(x)int operator!()return i;void main()A a(10);cout<<!a;·必须与类发生联系(成员函数或友元);例:#include<iostream.h>

5、class Afriend int operator+(const A&,int);int i;public:A(int x):i(x)int operator!()return i;int operator+(const A& x,int k)return x.i+k;void main()A a(10);cout<<a+10;·参数的数量与算符的元数有关;对象内成员数据与外界数据的相互转换 外界数据向对象内成员数据的转换例:# include<>class Timeint sec,min,hour;friend void operator!

6、(Time&); public:Time (long );Time (int,int);Time (int,float);Time:Time (long s)hour=s/3600;min=s%3600/60;sec=s%3600%60;Time:Time (int h,float ms)hour=h;min=(int)ms;sec= (int)(ms-min)*60);void operator!(Time &t)cout<<<<:<<<<:<<<<n;void main()Time t1=10346;T

7、ime t2=Time(430,34);Time t3=Time(12,(float)4.3);!t1;!t2;!t3; 对象内成员数据向外界数据的转换使用特定的成员算符函数来实现。其通用声明与定义格式为:operator新类型(); return新类型表达式;使用该类特定成员算符函数时要遵循下述规定:·此算符函数必须是类成员函数;·不必定义函数的返回值类型,其格式中的“新类型”一项就是用来充当返回类型的;·由于只能用类成员数据而不允许带任何参数;·引用时可直接使用对象名(可能需要类型强制);例:# include <iostream.h>c

8、lass Timeint sec,min,hour; public: Time(int h,int m,int s):hour(h),min(m),sec(s) operator unsigned long() return(unsigned long)hour*3600+(unsigned long)min*60+(unsigned long)sec; operator double()return(double)hour*60.+(double)min+(double)sec/60.; operator float()return(float)hour+(float)min/60.+(fl

9、oat)sec/3600.;void main()Time ts(12,48,53);unsigned long t1_s=ts;double t2_s=ts;/等效于double t2_s; t2_s=(double)ts;float t3_s=ts; cout<<”Seconds=”<<t1_s<<” Minites =”<<t2_s<<”hours =”<<t3_s<<n; cout<<”Seconds=”<<(unsigned long)ts<<”Minites =”

10、<<(double)ts<<”hours=”<<(float)ts;流输入和输出流处理类与流算符函数·了解流类的大致结构;·推论出标准的流算符函数:“cin>>”和“cout<<”应导成:cin.operator>>()和cout<<()的形式;·流算符函数的参数连导机制源于下述的重载声明:istream& operator>>(istream&);istream& operator>>();ostream& operator

11、<<(ostream&);ostream& operator<<();常用流算符函数的参数此参数都是“cin>>”和“cout<<”算符函数可以支持的类型,所以可使用非常方便设定一些简单的输入、输出格式。·入、出整数数制设定参数dec、hex和oct例:int i ,j;long l;char c,*s;cin>>i>>hex>>l>>c>>j>>s;/设定的状态要到下一个不同状态才变·回车换行函数endl;·强制发送输出缓存函数

12、flush;·取消输入结束符函数ws;常用的Ostream和Istream类库函数上述参数的格式设置能力有限,较为复杂的格式设置还要靠两个类库中的函数支持。为了使用上的方便,多数格式设置函数的返回值都是“ostream&”、“istream&” 或“cout<<”和“cin>>”算符函数的参数允许的数据类型。·输入、输出域宽度设置函数“SMANIP( int ) setw(int)”例:char *f =”12345”,*g =”678”;cout<<f<<setw(6)<<g<<set

13、w(4)<<f<<g;/显示时为:123456781234678·向输出域中填充字符的函数“SMANIP( int ) setfill(int)”例: cout<<setw(10)<<setfill(.)<<”1234”;/ 输出显示为“.1234”·设置浮点数输出显示精度函数“SMANIP( int ) setprecision(int)”例: float e=2.71828; cout<<setprecision(4)<<e;/ 显示为常用的Ios类格式表除了上述的函数设置格式以外,Io

14、s类中还声明了一系列的用于设置输入、输出格式的枚举型常数表。下表便是其中的最常用的一个:enumskipws=0x0001, /skip writespace on input,入left=0x0002, /left-adjust output,出/*adjustfield*/right=0x0004, /right-adjust output,出internal=0x0008, /fill after + or 0x,出dec= 0x0010, /decimal conversion,入出oct=0x0020, /octal conversion,入出hex=0x0040, /hexidec

15、imal conversion,入出showbase =0x0080, /use base indicator on output,出/*basefield*/showpoint =0x0100, /force decimal point(floating output),出uppercase =0x0200, /upper-case hex output,出showpos = 0x0400, /add+to positive integers,出scientific = 0x0800, /use 1.2345E2 floating notation,出/*floatfield*/fixed=

16、 0x1000, /use 1.2345 floating notation,出;与之相配套的是一组流类库函数的应用:函 数 声 明功 能long ios:flags();long ios:flags(long);long ios:setf(long,long);long ios:setf(long);long ios:unsetf(long);带回当前状态标志值设定当前的整个状态标志并带回前一状态标志值设定状态标志位,抵消第二参量指定的域中与新标志互斥的位,并带回所设的结果状态标志值在原状态标志基础上插入所需的状态标志,并带回所设的结果状态标志值恢复C+语言系统的缺省标志值并带回原来未清的状

17、态值使用格式表以及配套流类库函数的特点是:·设置的格式状态恒久;·可以随时获知当前的格式状态;·格式状态互斥问题得到较好的解决;·配套流类库函数要独立使用;例:cout<<cout.unsetf(ios:fixed)<<cout.setf(ios:scientific);/本例实现了浮点格式的转换cout.setf(ios:left,ios:adjustfield);cout<<setw(10)<<hex<<15045;/执行本例后显示为:0x3ac5int i=34;cout.setf(ios

18、:hex,ios:basefield);cout<<i<<endl;cout.setf(ios:showbase);cout<<i;/两次的显示结果分别为22和0x22。流类库宏的应用在文件中声明了许多很有用的宏,可以方便地使流输入、输出得到简化。以下以简化输出宏OAPP的应用为样本,试图阐明其中的实现原理:OAPP的声明如下:#define OAPP(T) _OAPP_#T#define class OAPP(T) public:OAPP(T)(ostream& (*f)(ostream&,T) : _fp(f) OMANIP(T) ope

19、rator()(T t) return OMANIP(T)(_fp,t); private:ostream& (* _fp)(ostream&,T); ;上述声明在编译时首先变形为:class _OAPP#T public:_OAPP#T (ostream& (*f)(ostream&,T) : _fp(f) OMANIP(T) operator()(T t) return OMANIP(T)(_fp,t); private:ostream& (* _fp)(ostream&,T); ;声明中的OMANIP(T)是ostream.h头文件中的另一

20、个宏。在实际代换后将成为_OAPP#T的同一类型(当然参数T仍要代入)。例:#include<iostream.h>#include<iomanip.h>ostream &lin(ostream &mo,int n) for(int i=0;i<n;i+)mo<<"n-" return mo;OAPP (int) nl(lin);void main() cout<<nl(3);/等效于lin(cout,3);本例中代换后的新类的形式如下:class nl public:nl (lin) : _fp(lin

21、) nl operator()(int t) return nl(_fp,t); /*构造新对象*/private:ostream& (* _fp)(ostream&,int); ;在nl类中系统声明了如下的友元:friend ostream& operator<<(ostream& s, const nl& sm) (*(sm._fp)(s,sm._tp); return s; 于是当执行“cout<<nl(3);”中的“nl(3)”后会得到一个nl的类对象,可假想为x(参数3在构造时已被记录在nl类对象中的_tp变量中)。则“

22、cout<<x;”可被表示为:”cout.operator<<(cout,x);”。而x实际上是函数型指针,必然引起上述友元函数的的动作,进而导致用户程序的执行。其它一些常用的流输入、输出函数的应用输入、输出流类库函数的数量非常多,相对常用的列于下表:函 数 声 明功 能 声 明int get();读入下一个字符,带回其int型码值(0-0xff)相当于C语言中的getchar()。int peek();功能同上,但并不后移其指针,所以若连续多次用peek()将读入同一个字符。istream &get(char&);功能同上,但值以引用型字符带回。ist

23、ream &get(char*,int,char= n);读入一个字串,长度由int参数指定,缺省结束标志(char型参数)若不指明,则为回车换行。istream &getline(char*,int,char=n);功能同上。istream &read(char *, int);读入一个字串,长度由int给出。istream &putback(char);将参量带入的字符回送接受缓存,大体等价于函数。istream &ignore(int=l, int=EOF);凡读入首参数指定之值便跳过(读而不存),第二参数为结束码。ostream &put

24、(char);输出指定的字符。ostream &write(char*, int);以第二参数的值为长度输出首参数地址的字符。流算符函数的重载流算符函数在重载时通常是以友元的形式实现的。利用流算符函数的重载可以大大简化用户类对标准流输入、输出的操作。例:#include<iostream.h>class Afriend ostream& operator(ostream&,const A&);int i;public:A(int x):i(x);ostream& operator(ostream& cs,const A& x)

25、cs<<”I=”<<x.i<<endl;void main()A a(10),b(100);cout<<a<<b;/此表达式应如何分解?流文件的应用 流文件类流文件基类Fstream也是Ios类的派生类。此外Fstream类还有如下图所示的派生结构:流文件声明与打开流文件的通用声明格式为:fstreamifstream文件对象名 (char*filename,打开方式常量表);ofstream打开方式常量表是Ios类中声明的枚举型常量表,其内容如下:enum open_modein = 0x1, /进行读操作。out=0x2, /进行

26、写操作。ate=0x4, /初打开文件时,文件指针一定定位到文件末尾备写。app=0x8,/每次写文件时,文件指针都自动定义到文件末尾作为append。trunc=0x10;/当写文件时,将文件当前指针以后的原有内容全部删除。nocreate=0x20, /若文件已存在,则不新建文件,否则打开失败。noreplace=0x40,/若文件已存在,则不取代同名文件,并使打开失败。binary=0x80, /打开以二进制方式读写,以上三种则为text方式。;此表借助类库函数打开文件:打开流文件的方法流文件的打开即可以在定义流文件对象的同时打开,也可以借助流类库函数来实现。例:fstream f(“t

27、est.dat”,ios:out|ios:in); 流文件的打开类库函数声明格式: 文件对象名.open(char *filename,打开方式常量表);例:#include <fstream.h>void main()fstream fl;fl.open(“test.dat”,ios:out|ios:binary);流文件输入、输出函数鉴于流文件是由流类派生而来,故可以使用所有的Ios类中的输入、输出类库函数。输入函数是由一组重载函数构成的:·读取一个字符函数声明:istream& get(char&);·读取一串字符函数声明:istream&

28、amp; get(char*,int,char =”n”);·读取一行字符函数声明:istream& getline(char*,int,char =n);输出函数如下:·函数声明:ostream& put( char ch );例1:读取一个字符char ch;fstream f(“test.txt”, ios:in);f.get(ch);例2:读取一串字符char p1025;fstream f(“”,ios:in);f.get(p,1024,0);例3:向文件内写一个字符fstream f(“”,ios:out);f.put(A);利用流算符函数实现流文件的输入、输出继承了Ios类的流文件类理所当然的也继承了相应的流算符函数。因而可以直接使用这些流算符函数实现流文件的输入

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论