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