当前位置: 首页 > 文档资料 > C++大学教程 >

8.17 自助练习题

优质
小牛编辑
118浏览
2023-12-01

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)重载运算符==和!=,使之能比较两个复数。

1 // Fig. 8.7: complex1.h
2 // Definition of class Complex
3 #ifndef COMPLEX1_H
4 #define COMPLEX1_H
5
6 class Complex {
7 public:
8 Complex( double = 0.0, double = 0.0 ); // constructor
9 Complex operator+( const Complex & ) const; // addition
10 Complex operator-( const Complex & ) const; // subtraction
11 const Complex &operator=( const Complex & ); // assignment
12 void print() const; // output
13 private:
14 double real; // real part
15 double imaginary; // imaginary part
16 };
17
18 #endif
19 // Fig. 8.7:complex1.cpp
20 // Member function definitions for class Complex
21 #include <iostream.h>
22 #include "complex1.h"
23
24 // Constructor
25 Complex::Complex( double r, double i )
26 : real( r ), imaginary( i ) { }
27
28 // Overloaded addition operator
29 Complex Complex::operator+( const Complex &operand2 ) const
3O {
31 return Complex( real + operand2.real,
32 imaginary + operand2.imaginary );
33 }
34
35 // Overloaded subtraction operator
36 Complex Complex::operator-( const Complex &operand2 ) const
37 {
38 return Complex( real - operand2.real,
39 imaginary - operand2.imaginary );
4O }
41
42 // Overloaded = operator
43 const Complex& Complex::operator=( const Complex &right )
44 {
45 real = right.real;
46 imaginary = right.imaginary;
47 return *this; // enables cascading
48 }
49
51 void Complex::print() const
52 { cout << '(' << real << ", "<< imaginary << ')'; }
53 // Fig. 8.7:fig08_07.cpp
54 // Driver for class Complex
55 #include <iostream.h>
56 #include "complex1.h"
57
58 int main()
59 {
60 Complex x, y( 4.3, 8.2 ), z( 3.3, 1.1 );
61
62 cout << "x: ";
63 x.print();
64 cout << "\ny: ";
65 y.print();
66 cout << "\nZ: ";
67 z.print();
68
69 x = y + z;
70 cout << "\n\nx = y + z:\n";
71 x.print();
72 cout << " = ";
73 y.print();
74 cout <<" + ";
75 z.print();
76
77 x = y - z;
78 cout << "\n\nx = y - z:\n";
79 x.print();
80 cout << "=" ;
81 y.print();
82 cout << " - " :
83 z.print();
84 cout << endl;
85
86 return 0;
87 }

输出结果:

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.7 演示 Complex 类

8.16 32 位整数的机器所能表示的整数范围大致是-20亿到+20亿,在这个范围内的操作一般不会出现问题。但是有很多应用程序可能要使用超出上述范围的整数,C++可以满足这个需求,这需要建立一个新的数据类型。考虑图8.8中的类HugeInt,仔细研究以后,完成下列问题:

a)准确描述它是如何操作的。
b)该类有什么限制,
c)重载乘法运算符*。
d)重载除法运算符/。
e)重载所有的关系运算符和相等运算符。

1 // Fig. 8.8: hugeintl.h
2 // Definition of the Hugelnt clas~
3 #ifndef HUGEINT1_H
4 #define HUGEINT1_H
5
6 #include <iostream.h>
7
8 class HugeInt {
9 friend ostream &operator<<( ostream &, HugeInt & );
10 public:
11 HugeInt( long = 0 ); // conversion/default constructor
12 HugeInt( const char * ); // conversion constructor
13 HugeInt operator+( HugeInt & ); // add another HugeInt
14 HugeInt operator+( int ); // add an int
15 HugeInt operator+( const char * ); // add an int in a char *
16 private:
17
18 };
19
20 #endif
21 // Fig. 8.8: nugeintl.cpp
22 // Member and friend function definitions for class HugeInt
23 #include <string.h>
24 #include "hugeint1.h"
25
26 // Conversion constructor
27 HugeInt::HugeInt( long val )
28 {
29 int i;
30
31 for( i = 0; i <= 29;i ++ )
32 integer[ i ] = 0; // initialize array to zero
33
34 for ( i = 29; val != 0 && i >= 0; i-- ) {
35 integer[ i ] = val % 10;
36 val /= 10;
37 }
38 }
39
40 HugeInt::HugeInt( const char *string )
41 {
42 int i, j;
43
44 fori( i =O i <= 29; i++ )
45 integer[ i ] = 0;
46
47 for ( i = 30 - strlen( string ), j = 0; i <= 29; i++, j++ )
48 integer[ i ] = string[ j ] - '0';
49 }
50
51 // Addition
52 HugeInt HugeInt::operator+( HugeInt &op2 )
53 {
54 HugeInt temp;
55 int carry = 0;
56
57 for( int i = 29; i >= 0; i --){
58 temp.integer[ i ] = integer[ i ] +
59 ep2.integer[ i ] + carry;
6O
61 if ( temp.integer[ i ] > 9 ) {
62 temp.integer[ i ] %= 10;
63 carry = 1;
65 else
66 carry = 0;
67 }
68
69 return temp;
70 }
71
72 // Addition
73 HugeInt HugeInt::operator+( int op2 )
74 { return *this + HugeInt( op2 ); }
75
76 // Addition
77 HugeInt HugeInt::operator+( const char *op2 )
78 { return *this + HugeInt( op2 ); }
79
80 ostream& operator<<( ostream &output, HugeInt &num )
81 {
82 int i;
83
84 for ( i = 0; { num.integer[ i ] == 0 ) && ( i <= 29 ); i++ )
85 ; // skip leading zeros
86
87 if ( i == 30 )
88 output << 0;
89 else
90 for ( ; i <= 29; i++ )
91 output << num.integer[ i ];
92
93 return output;
94 }
95 // Fig. 8.8: figO8_08.cpp
96 // Test driver for HugeInt
97 #include <iostream.h>
98 #include "hugeint1.h"
99
100 int main()
101 {
102 HugeInt n1( 7654321 ), n2( 7891234 ),
103 n3( "99999999999999999999999999999" ),
104 n4( "1" ), n5;
105
106 cout << "n1 is "<< n1 << "\nn2 is "<< n2
107 << "\nn3 is" << n3 << "\nn4 is" << n4
108 << "\nn5 is" << n5 << "\n\n";
109
110 n5 = n1 + n2;
111 cout << n1 <<" + "<< n2 << " = " << n5 << "\n\n";
112
113 cout << n3 <<" +" << n4 << "\n= "<< ( n3 + n4 )
114 << "\n\ n";
115
116 n5 = n1 + 9;
117 cout << n1 <<" + " << 9 << "=" << n5 << "\n\n";
118
119 n5 = n2 + "10000";
120 cout << n2 << " + " << "10000" << " = " << n5 << endl;
121
122 return 0;
123 }

输出结果:

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.8 用户自定义的巨型整数类

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<<作为成员函数,试在程序中使用上述语句以证明程序能够运行。