8.1 填空:
a)设a和b是两个整型变量,我们用a+b的形式求这两个变量的和;设c和d为浮点型变量,我们用c+d的形式求这两个变量的和。显然,运算符+具有不同的用途,这是——的例子。
b)关键字——引出了重载运算符函数的定义。
c)要在类的对象上使用运算符,除了运算符——和——以外,其他的必须都要被重载。
d)重载不能改变运算符的——、——和——。
8.2 解释C++中的运算符 <<和>>的多层含义。
8.3 C++中,在什么时候可以使用名字operator/
8.4(判断对错)在C++中,只能重载已有的运算符。
8.5 在C++中,重载运算符的优先级和原先未重载的运算符的优先级相比,哪一个优先级高
8.1 a)运算符重载。b)operator。c)=、&。d)优先级、结合律和数量。
8.2 根据上下文,运算符>>可能是右移位运算符,也可能是流读取运算符。同样,运算符<<可能是左移位运算符,也可能是流插入运算符。
8.3 运算符重载时可以使用operator/,它可以是提供运算符/的重载版本的函数名。
8.4 正确。
8.5 相同。
8.6 尽可能多地举出C和C++中隐式运算符重载的例子。给出需要在C++中显式重载运算符的具有说服性的例子。
8.7 C++中不能被重载的运算符有——、——、——、——和——。
8.8 字符串连接需要两个操作敷,即两个要被连接的字符串。本章介绍了如何实现将第二个String对象连接到第一个String对象右边的一个重载的连接运算符,这种连接会修改第一个String对象。在有些实际应用中,需要在不修改String参数的情况下产生一个已连接的String对象,请实现允许如下操作的operator+:string1 = string2 + string3;
8.9(基本运算符重载练习)列出C++的所有可重载的运算符,并对每个可重载的运算符,列出它们在用于几个不同的类时的一种或者几种可能的含义。建议试试下面的类:
a)数组
b)堆栈
c)字符串
完成后,说明哪些运算符的含义可适用于大量的类,哪些运算符重载的价值极小,哪些运算符具有歧义性。
8.10现在将上一个问题所描述的过程反过来,列出C++中每个可重载的运算符,对于每个运算符,列出你认为它应该代表的基本操作。如果有非常好的操作,把它们列出来。
8.11(项目)C++是一门正在发展中的语言,并且总是有许多新的语言开发出来。除了现有的运算符以外,你认为还有哪些运算符可以添加到C++或者添加到像C++这样既支持过程化编程又支持面向对象编程的未来语言中呢,请将你的建议寄给ANSIC++委员会。
8. 12重载函数调用运算符()的一个较好的例子是将以下的二维数组的下标表示方法:
chessBoard[ row ][ column ]
改为常用的表示方法:
chessboard( row,column )
试重载函数调用运算符()支持上述表示方法。
8.13生成DoubleSubscriptedArray类,与图8.4的Array类的特性相似。构造时,类应生成任意行数和列数的数组。类用operator()进行双下标操作。例如,在3 x 5的DoubleSubscriptedArray数组a中,用户可以用s(1,3)访问行1列3的元素。记住,operator()可以接收任何参数(关于operator()的例子,见图8.5的String类)。双下标数组的基本表达方式为rows*columns个元素的单下标数组。函数operator()应通过正确的指针算法访问数组的每个元素。实际上,
operator()应有两个版本,一个返回int &,使DoubleSubscriptedArray的元素可以用作左值,一个返回cons int&,使const DoubleSubscfiptedArray的元素可以用作右值。这个类还应提供下列运算符==;!=、=、<<(以行和列格式输出数组)和>>(输入整个数组内容)。
8.14重载下标运算符使之返回集合中最大的元素、次最大的元素以及第三大的元素等等。
8.15考虑图8.7中的类Complex,该类可以执行复数操作,复数的格式为:
realPart + imaginaryPart * i
其中i是 -1 的平方根。
a)修改该类,使之能用重载的 >>和<<输入和输出复数(当然要从Complex类中删除打印函数)。
b)重载乘法运算符,使之能执行两个复数的代数乘法。
c)重载运算符==和!=,使之能比较两个复数。
// Fig. 8.7: complex1.h // Definition of class Complex #ifndef COMPLEX1_H #define COMPLEX1_H class Complex { public: Complex( double = 0.0, double = 0.0 ); // constructor Complex operator+( const Complex & ) const; // addition Complex operator-( const Complex & ) const; // subtraction const Complex &operator=( const Complex & ); // assignment void print() const; // output private: double real; // real part double imaginary; // imaginary part }; #endif // Fig. 8.7:complex1.cpp // Member function definitions for class Complex #include < iostream.h> #include "complex1.h" // Constructor Complex::Complex( double r, double i ) : real( r ), imaginary( i ) { } // Overloaded addition operator Complex Complex::operator+( const Complex &operand2 ) const O { return Complex( real + operand2.real, imaginary + operand2.imaginary ); } // Overloaded subtraction operator Complex Complex::operator-( const Complex &operand2 ) const { return Complex( real - operand2.real, imaginary - operand2.imaginary ); } // Overloaded = operator const Complex& Complex::operator=( const Complex &right ) { real = right.real; imaginary = right.imaginary; return *this; // enables cascading } void Complex::print() const { cout << '(' << real << ", "<< imaginary << ')'; } // Fig. 8.7:fig08_07.cpp // Driver for class Complex #include < iostream.h> #include "complex1.h" int main() { Complex x, y( 4.3, 8.2 ), z( 3.3, 1.1 ); cout << "x: "; x.print(); cout << "\ny: "; y.print(); cout << "\nZ: "; z.print(); x = y + z; cout << "\n\nx = y + z:\n"; x.print(); cout << " = "; y.print(); cout <<" + "; z.print(); x = y - z; cout << "\n\nx = y - z:\n"; x.print(); cout << "=" ; y.print(); cout << " - " : z.print(); cout << endl; return 0; }
输出结果:
x: (0,0)
y: (4.3, 8.2)
z: (3.3, 1.1)
x = y + z:
(7.6, 9.3) = (4.3, 8.2) + (3.3, 1.1)
x = y - z:
(1, 7.1) = (4.3, 8.2) - (3.3, 1.1)
8.16 32位整数的机器所能表示的整数范围大致是-20亿到+20亿,在这个范围内的操作一般不会出现问题。但是有很多应用程序可能要使用超出上述范围的整数,C++可以满足这个需求,这需要建立一个新的数据类型。考虑图8.8中的类HugeInt,仔细研究以后,完成下列问题:
a)准确描述它是如何操作的。
b)该类有什么限制,
c)重载乘法运算符*。
d)重载除法运算符/。
e)重载所有的关系运算符和相等运算符。
// Fig. 8.8: hugeintl.h // Definition of the Hugelnt clas~ #ifndef HUGEINT1_H #define HUGEINT1_H #include < iostream.h> class HugeInt { friend ostream &operator<<( ostream &, HugeInt & ); public: HugeInt( long = 0 ); // conversion/default constructor HugeInt( const char * ); // conversion constructor HugeInt operator+( HugeInt & ); // add another HugeInt HugeInt operator+( int ); // add an int HugeInt operator+( const char * ); // add an int in a char * private: }; #endif // Fig. 8.8: nugeintl.cpp // Member and friend function definitions for class HugeInt #include < string.h> #include "hugeint1.h" // Conversion constructor HugeInt::HugeInt( long val ) { int i; for( i = 0; i <= 29;i ++ ) integer[ i ] = 0; // initialize array to zero for ( i = 29; val != 0 && i >= 0; i-- ) { integer[ i ] = val % 10; val /= 10; } } HugeInt::HugeInt( const char *string ) { int i, j; fori( i =O i <= 29; i++ ) integer[ i ] = 0; for ( i = 30 - strlen( string ), j = 0; i <= 29; i++, j++ ) integer[ i ] = string[ j ] - '0'; } // Addition HugeInt HugeInt::operator+( HugeInt &op2 ) { HugeInt temp; int carry = 0; for( int i = 29; i >= 0; i --){ temp.integer[ i ] = integer[ i ] + ep2.integer[ i ] + carry; O if ( temp.integer[ i ] > 9 ) { temp.integer[ i ] %= 10; carry = 1; else carry = 0; } return temp; } // Addition HugeInt HugeInt::operator+( int op2 ) { return *this + HugeInt( op2 ); } // Addition HugeInt HugeInt::operator+( const char *op2 ) { return *this + HugeInt( op2 ); } ostream& operator<<( ostream &output, HugeInt &num ) { int i; for ( i = 0; { num.integer[ i ] == 0 ) && ( i <= 29 ); i++ ) ; // skip leading zeros if ( i == 30 ) output << 0; else for ( ; i <= 29; i++ ) output << num.integer[ i ]; return output; } // Fig. 8.8: figO8_08.cpp // Test driver for HugeInt #include < iostream.h> #include "hugeint1.h" int main() { HugeInt n1( 7654321 ), n2( 7891234 ), n3( "99999999999999999999999999999" ), n4( "1" ), n5; cout << "n1 is "<< n1 << "\nn2 is "<< n2 << "\nn3 is" << n3 << "\nn4 is" << n4 << "\nn5 is" << n5 << "\n\n"; n5 = n1 + n2; cout << n1 <<" + "<< n2 << " = " << n5 << "\n\n"; cout << n3 <<" +" << n4 << "\n= "<< ( n3 + n4 ) << "\n\ n"; n5 = n1 + 9; cout << n1 <<" + " << 9 << "=" << n5 << "\n\n"; n5 = n2 + "10000"; cout << n2 << " + " << "10000" << " = " << n5 << endl; return 0; }
输出结果:
n1 is 7654321
n1 is 7891234
n1 is 99999999999999999999999999999
n1 is 1
n1 is O
7654321 + 7891234 = 15545555
99999999999999999999999999999 +1
= 1OO000000000000000000000000000
7654321 + 9 = 7654330
7891234 + 10000 = 7901234
8.17建立类RationalNumber(分数类),使之具有下述功能:
a)建立构造函数,它能防止分母为0、当分数不是最简形式时进行约分以及避免分母为负数。
b)重载加法、减法、乘法以及除法运算符。
c)重载关系运算符和相等运算符。
8.18仔细研究C的字符串处理库函数,分别把这些函数作为类String的一部分予以实现,然后用这些函数执行文本操作。
8.19开发多项式类Polynomial,多项式的每一项用数组表示,每项包含一个系数和一个指数。
例如:
2x4
的指数为4,系数为2。请开发一个完整的Polynomial类,包括构造函数、析构函数以及”get”函数和“set”函数。该类还要提供下述重载的运算符:
a)重载加法运算符+,将两个多项式相加。
b)重载减法运算符-,将两个多项式相减。
c)重载赋值运算符=,将一个多项式赋给另外一个多项式。
d)重载乘法运算符*,将两个多项式相乘。
c)重载加法赋值运算符+=、减法赋值运算符-=以及乘法赋值运算符*=。
8.20 图8.3的程序包含下列注释语句:
// Overloaded stream-insertion operator(cannot be // a member function if we would like to invoke it with // cout << somePhoneNumber;)
实际上,它不能是ostream类的成员函数,但可以是PhoneNumber类的成员函数,只要以下列方式调用:
somePhoneNumber.operator <<(cout); 或 somePhoneNumber << cout;
改写图8.3的程序.用重载的流插入operator <<作为成员函数,试在程序中使用上述语句以证明程序能够运行。