8.3自定义的操纵算子 8.3.1不带参数的操纵算子 定义不带参数的操纵算子比较简单。下面的程序定义了一个名为 newline的操纵算子, 它和预定义的操纵算子endl具有相同的功能。 例89:定义一个名为 newline的操纵算子EX89CPP 操纵算子的目的主要是解决在流的插入或提出表达式中使用函数调用所引起的问题。 个简单的操纵处算符是一个说明为 type& fun( type&); 的函数地址。这里type可以是 Istream、 ostream、 Iostream或ios类的类名。 在 Istream类中说明了两个特殊的插入函数 istream& istream: operator>>(istream&(*an Fun)(istream&)); isteam& istream: operator>>(ios& (anFun)(ios&)) 在 ostream类中也说明了两个特殊的插入函数 stream& ostream: operator>>(ostream&(an Fun)(ostream&)) steam& ostream: operator>>(ios&(anFun)(ios&) 这些成员函数都接收一个函数指针参数。当这些成员函数被启动时,它们又简单地通过 这个函数指针调用这个指针所指向的函数 语句cout<<” A line”<< newline<<” another line”;计算过程 首先计算优先级比运算符<<高的运算符组成的表达式,然后对表达式 cout<<” Aline 使用插入操作符 ostream: operator<<(char*),最后,表达式 cout<<newline 使用上面列出的 ostream类的第一个插入函数调用 newline c 8.3.2带有一个int或long类型参数的操纵算子 由于函数调用运算符的优先级高于插入符,所以语句cou<a< <setprecsion(2)<<b中先 调用函数 setprecision。但是,函数 setprecision必须在插入符输出了变量a之后才能设置精 度,因此在调用函数 setprecision时不能立即设置精度,相反,它应返回某个对象,这个对 象可被它所在的类中重载的插入符用来为变量b设置所需的精度 C++系统提供的头文件 iomanip. h中定义了一系列的宏,来帮助程序员定义带有一个参 数的操纵算子。这个头文件中还特别定义了帮助程序员定义一个带有int类型或long类型参 数的操纵算子所需的类。在该文件中, setprecision被定义为: SMANIP (int) setprecision( int n); 函数 setprecision()返回 SMANIP(int)类的一个对象, SMANIP(int)类的构造函数 在这个对象中保存下来一个函数的地址和它的参数值。所以语句 (cout<<ax< csetprecsion(2)<b,)的计算过程是 1、首先计算表达式a、b和 setprecision的值,函数 setprecision返回一个 SMANIP(int) 类的一个对象。 2、使用插入符 ostream: operator<<(foat将表达式a的值以原有的精度输出。 3、使用插入符 operator<<( Gos&, SMANIP(int访问 setprecision所返回的对象,使用这个
8.3 自定义的操纵算子 8.3.1 不带参数的操纵算子 定义不带参数的操纵算子比较简单。下面的程序定义了一个名为 newline 的操纵算子, 它和预定义的操纵算子 endl 具有相同的功能。 例 8_9:定义一个名为 newline 的操纵算子 EX8_9.CPP 操纵算子的目的主要是解决在流的插入或提出表达式中使用函数调用所引起的问题。 一个简单的操纵处算符是一个说明为 type& fun(type&); 的函数地址。这里 type 可以是 istream、ostream、iostream 或 ios 类的类名。 在 istream 类中说明了两个特殊的插入函数: istream& istream::operator>>(istream& (*anFun)(istream&)); isteam& istream::operator>>(ios& (*anFun)(ios&)); 在 ostream 类中也说明了两个特殊的插入函数: ostream& ostream::operator>>(ostream& (*anFun)(ostream&)); osteam& ostream::operator>>(ios& (*anFun)(ios&)); 这些成员函数都接收一个函数指针参数。当这些成员函数被启动时,它们又简单地通过 这个函数指针调用这个指针所指向的函数。 语句 cout<<”A line”<<newline<<”another line”; 计算过程: 首先计算优先级比运算符<<高的运算符组成的表达式,然后对表达式 cout<<”A line” 使用插入操作符 ostream::operator<<(char *),最后,表达式 cout<<newline 使用上面列出的 ostream 类的第一个插入函数调用 newline。 8.3.2 带有一个 int 或 long 类型参数的操纵算子 由于函数调用运算符的优先级高于插入符,所以语句 cout<<a<<setprecsion(2)<<b;中先 调用函数 setprecision。但是,函数 setprecision 必须在插入符输出了变量 a 之后才能设置精 度,因此在调用函数 setprecision 时不能立即设置精度,相反,它应返回某个对象,这个对 象可被它所在的类中重载的插入符用来为变量 b 设置所需的精度。 C++系统提供的头文件 iomanip.h 中定义了一系列的宏,来帮助程序员定义带有一个参 数的操纵算子。这个头文件中还特别定义了帮助程序员定义一个带有 int 类型或 long 类型参 数的操纵算子所需的类。在该文件中,setprecision 被定义为: SMANIP(int) setprecision(int n); 函数 setprecision()返回 SMANIP(int)类的一个对象,SMANIP(int)类的构造函数 在 这 个 对 象 中 保 存 下 来 一 个 函 数 的 地 址 和 它 的 参 数 值 。 所 以 语 句 (cout<<a<<setprecsion(2)<<b;)的计算过程是: 1、首先计算表达式 a、b 和 setprecision 的值,函数 setprecision 返回一个 SMANIP(int) 类的一个对象。 2、使用插入符 ostream::operator<< (float)将表达式 a 的值以原有的精度输出。 3、使用插入符 operator<<(ios&,SMANIP(int))访问 setprecision 所返回的对象,使用这个
对象中保存的函数 setprecision的地址和参数2设置精度 4、使用 ostream: operator<<(floa)按新设置的精度输出表达式b的值 例810:设计一个带有一个int类型参数的操纵算子star(EX810.CPP) OMANIP(int是 iomanip. h中定义的一个类名。第二个star函数仅有的功能是使用 OMANIP(int)类的构造函数 OMANIP (int ): OMANIP(int) (ostream&(an Fun)(ostream, int), int); 建立一个 OMANIP(int)的一个对象,并返回这个对象。由于 OMANIP(int)的构造函数的 第一个参数的函数原型为: ostream&fun( ostream&,int; 所以在 return语句中使用了第一个star函数的地址。 为了便于以后叙述,将建立一个对象的函数称为操纵算子。如上例的函数 OMANIP(int)star(int) 而将完成操纵算子的功能的函数称为操纵函数,如上例中的函数 ostream& star(ostream&, int) 操纵算子和操纵函数协同完成对流所需的操作 在 iomanip. h中,针对ios、 istream、 ostream和 Iostream类分别预定义了 SMANIP(int)、 IMANIP(int)、 OMANIP(int)和 IOMANIP(int)类,以简化程序员定义带有一个nt类 型参数的操纵算子的工作。这些类分别用于需要ios、 Istream、 ostream和 Iostream类作为第 个参数类型的操纵函数中,但更主要地取决于在操纵算子中准备使用哪个类中的成员函 数。在 iomanip. h中也同样预定义了一个 SMANIP(ong入 IMANIP(long)、 OMANIP(long) 和 IOMANIP(long)类,供程序员用来定义带有一个long类型参数的操纵算子 8.3.3定义任意参数类型的操纵算子 我们为 complex类的对象定义一个 reformat操纵算子,它用于设置所有 complex类的 对象输出(或输入)时的域宽、精度和所使用的分隔符。设有 complex类的两个对象cl和 c2,它们分别表示复数5+3i和4+2i,下面是使用操纵算子 reformat的一个语句示例: 例811:定义任意参数类型的操纵算子示例之一(EX811.CPP)。 例812:定义任意参数类型的操纵算子示例之二(EX812.CPP)
对象中保存的函数 setprecision 的地址和参数 2 设置精度。 4、使用 ostream::operator<< (float)按新设置的精度输出表达式 b 的值。 例 8_10:设计一个带有一个 int 类型参数的操纵算子 star(EX8_10.CPP)。 OMANIP(int)是 iomanip.h 中定义的一个类名。第二个 star 函数仅有的功能是使用 OMANIP(int)类的构造函数: OMANIP(int)::OMANIP(int)(ostream& (*anFun)(ostream&,int),int); 建立一个 OMANIP(int)的一个对象,并返回这个对象。由于 OMANIP(int)的构造函数的 第一个参数的函数原型为: ostream& fun(ostream&,int); 所以在 return 语句中使用了第一个 star 函数的地址。 为了便于以后叙述,将建立一个对象的函数称为操纵算子。如上例的函数 OMANIP(int) star(int); 而将完成操纵算子的功能的函数称为操纵函数,如上例中的函数 ostream& star(ostream&,int); 操纵算子和操纵函数协同完成对流所需的操作。 在 iomanip.h 中,针对 ios、istream、ostream 和 iostream 类分别预定义了 SMANIP(int)、 IMANIP(int)、OMANIP(int)和 IOMANIP(int)类,以简化程序员定义带有一个 int 类 型参数的操纵算子的工作。这些类分别用于需要 ios、istream、ostream 和 iostream 类作为第 一个参数类型的操纵函数中,但更主要地取决于在操纵算子中准备使用哪个类中的成员函 数。在 iomanip.h 中也同样预定义了一个 SMANIP(long)、IMANIP(long)、OMANIP(long) 和 IOMANIP(long)类,供程序员用来定义带有一个 long 类型参数的操纵算子。 8.3.3 定义任意参数类型的操纵算子 我们为 complex 类的对象定义一个 setformat 操纵算子,它用于设置所有 complex 类的 对象输出(或输入)时的域宽、精度和所使用的分隔符。设有 complex 类的两个对象 c1 和 c2,它们分别表示复数 5+3i 和 4+2i,下面是使用操纵算子 setformat 的一个语句示例: 例 8_11:定义任意参数类型的操纵算子示例之一(EX8_11.CPP)。 例 8_12:定义任意参数类型的操纵算子示例之二(EX8_12.CPP)