这里写目录标题
- 一、复习题
 - 二、编程练习
 
一、复习题
1. 使用成员函数为Stonewt类重载乘法运算符,该运算符将数据成员与double类型的值相乘。注意,当用英石和磅表示时,需要进位。也就是说,将10英石8磅乘以2等于21英石2磅。
答:下面是原Stonewt类的声明,我们在其成员函数中重载乘法运算符(*)。
// Stonewt类声明
class Stonewt
{
private:
	enum {Lbs_per_stn = 14};  // 1英石等于14英镑
	int stone;  // 整数形式的英石
	double pds_left;  // 剩余的英镑
	double pounds;  // 总共多少英镑
public:
	Stonewt(double lbs);  // 一个参数的构造函数
	Stonewt(int stn, double lbs);  // 两个参数的构造函数
	Stonewt();  // 默认构造函数
	~Stonewt()  // 析构函数
	void show_lbs() const ;  // 以磅为单位显示体重
	void show_stn() const;  // 以英镑为单位显示体重
	// 乘法运算符重载
	Stonewt operator*(double n);
}
// 函数定义
// Stonewt类的乘法运算符重载
Stonewt Stonewt::operator*(double n) const
{
	return Stonewt(n*pounds);  // 用构造函数创建临时对象返回
}
 
2. 友元函数与成员函数之间的区别是什么?
答:从性质上看,成员函数是类定义的一部分,由类生成的所有对象均会共享类的一组成员函数。从功能上看,成员函数能够访问类内部的所有数据成员。而友元函数并不是类定义的一部分,而是一个具备特定的类访问权限的函数,友元函数从功能上说也能够直接访问所有类的成员,但是并不能隐式访问,而必须通过成员运算符用于参数传递的对象。
3. 非成员函数必须是友元函数才能访问类成员吗?
答:首先从访问控制上说,使用类对象的程序能直接通过类对象访问所有的公有数据接口,但无法访问类的私有数据接口。通过类的友元函数能够直接访问类内的所有数据成员和函数,包括具有私有访问权限的数据成员和成员函数。因此,片面地认为非成员函数必须是友元函数才能访问类成员是不正确的。
4. 使用友元函数为Stonewt类重载乘法运算符,该运算符将double值与Stone值相乘。
答:使用友元函数需要注意,在函数声明(函数原型)时,需要使用关键字friend,且需要在类内声明。定义时需要在类外,因为友元函数并不是该类的成员函数,函数定义不需要使用friend关键字,也不需要使用类名称限定。(上面有类声明,我就直接写函数声明和定义了)
// Stonewt类声明
class Stonewt
{
private:
	// ... 
public:
	// ...
	friend Stonewt operator*(double n, const Stonewt& s);
}
// 函数定义
Stone operator*(double n, const Stonewt& s)
{
	return Stonewt(n*s.pounds);  // 依旧使用构造函数创建临时变量返回
}	
 
5. 哪些运算符不能被重载?
答:C++中运算符的重载有一定的限制,重载运算符至少有一个参数是用户自定义的类型,不能创建新的运算符,不能违反原来运算符的语法法则,部分运算符不能重载。不能重载的运算符如下:
 a. sizeof——sizeof运算符
 b. .——成员运算符
 c. .*——成员指针运算符
 d. ::——作用域解析运算符
 e. ?:——条件运算符
 f. typeid——一个RTTI运算符
 g. const_cast——强制类型转换运算符
 h. dynamic_cast——强制类型转换运算符
 i. reintepret_cast——强制类型转换运算符
 j. static_cast——强制类型转换运算符
6. 在重载运算符=、()、[]、和->时,有什么限制?
答:首先包含复习题5说明的四条规则,重载运算符至少有一个参数是用户自定义的类型,不能违反运算符原来的语法规则,不能创建新的运算符,部分运算符不能重载。此外,大多数运算符可以通过成员或非成员函数进行重载,但上述四个运算符(=、()、[]和->)只能通过成员函数进行重载,不能使用友元函数进行重载。
7. 为Vector类定义一个转换函数,将Vector类转换为一个double类型的值,后者表示矢量的长度。
答:由于只有一条返回语句,直接在类声明中定义,使其成为内联函数(前缀inline关键字修饰)。
// Vector类声明
class Vector
{
private:
	// ...
public:
	// ... 
	operator double() const {return mag;}
}
 
二、编程练习
1. 修改程序清单11.15,使之将一系列连续的随机漫步者位置写入文件中。对于每个位置,用步号进行标识。另外,使程序将初始条件(目标距离和步长)以及结果小结写入该文件中。该文件内容如下。
 Target Distance:100,Step Size:20
 0:(x,y)=(0,0)
 1:(x,y)=(-11.4715,16.383)
 2:(x,y)=(-8.68807,-3.42232)
 …
 26:(x,y)=(42.2919,-78.2594)
 27:(x,y)=(58.6749,-89.7309)
 After 27 steps,the subject has the following location:
 (x,y)=(58.6749,-89.7309)
 or
 (m,a)=(107.212,-56.8194)
 Average outward distance per step = 3.97081
答:下面是作者重新编写的代码(读者也可以根据书上进行修改,添加头文件<fstream>,然后输出到文件中)。
Vector1.h头文件
#pragma once
// 头文件
#include <iostream>
// using 声明
using std::cout;
using std::endl;
// 名称空间VECTOR
namespace VECTOR
{
	// using 声明
	using std::ostream;
	// Vector类声明
	class Vector
	{
	public:
		enum Mode{RECT, POL};
		// RECT表示直角坐标,POL表示极坐标
	private:
		double x_;  // 横坐标
		double y_;  // 纵坐标
		double mag_;  // 向量的长度
		double ang_;  // 向量的方向
		Mode mode_;  // 使用哪一种表示方法
		// 私有方法声明
		void set_mag();
		void set_ang();
		void set_x();
		void set_y();
	public:
		// 公有方法声明
		Vector();  // 默认构造函数
		Vector(double n1, double n2, Mode form = RECT);  // 带参数的构造函数,默认为直角坐标表示方式
		void reset(double n1, double n2, Mode form = RECT);
		~Vector();  // 析构函数
		double xval() const { return x_; }
		double yval() const { return y_; }
		double magval() const { return mag_; }
		double angval() const { return ang_; }
		void polar_mode();  // 使用POL坐标
		void rect_mode();  // 使用RECT坐标
		// 运算符重载
		Vector operator+(const Vector& v) const;
		Vector operator-(const Vector& v) const;
		Vector operator-() const;
		Vector operator*(double n) const;
		// 友元
		friend Vector operator*(double n, const Vector& v);
		friend ostream& operator<<(ostream& os, const Vector& v);
	};
}
 
main1.cpp测试文件
// 头文件
#include "Vector1.h"
#include <ctime>
#include <cstdlib>
#include <fstream>
// using 编译指令
using VECTOR::Vector;
// using 声明
using std::cin;
using std::ofstream;
int main()
{
	// 定位文件
	ofstream fo;
	fo.open("rambler.txt", 'w');
	// 设置随机数种子
	srand((unsigned)time(0));
	// 需要的变量
	double step;  // 步长
	double distance;  // 距离
	int steps = 0;  // 走了几步
	Vector result(0.0, 0.0);  // 存储每走一步的结果
	// 输入距离和步长
	fo << "Target Distance: ";
	while (cin >> distance)
	{
		fo << distance << ", ";
		fo << "Step Size: ";
		if (!(cin >> step))
			break;
		fo << step << endl;
		fo << steps << ": " << "(x, y) = "
			<< "(" << result.xval() << ", "
			<< result.yval() << ")" << endl;
		while (result.magval() < distance)
		{
			double ang = rand() % 360;
			Vector tmp(step, ang, Vector::POL);
			result = result + tmp;
			++steps;
			fo << steps << ": " << "(x, y) = "
				<< "(" << result.xval() << ", "
				<< result.yval() << ")" << endl;
		}
		// 按格式输出
		fo << "After " << steps << "steps, the subject has the following location:\n"
			<< "(x, y) = " << "(" << result.xval() << ", " << result.yval() << ")\n"
			<< "or\n" << "(m, a) = " << "(" << result.magval() << ", " << result.angval()
			<< ")\n";
		fo << "Average outward distance per step = " << distance / steps << endl;
	}
	// 关闭文件
	fo.close();
	return 0;
}
 
Vector1.cpp方法定义文件
// 头文件
#include "Vector1.h"
#include <cmath>
// using 声明
using std::sqrt;
using std::sin;
using std::cos;
using std::atan;
using std::atan2;
// 名称空间VECTOR
namespace VECTOR
{
	// 符号常量
	const double Rad_to_Deg = 45.0 / atan(1.0);  // 1弧度转度
	// 私有方法定义
	void Vector::set_mag()
	{
		mag_ = sqrt(x_ * x_ + y_ * y_);
	}
	void Vector::set_ang()
	{
		if (x_ == 0 && y_ == 0)
			ang_ = 0;
		else
			ang_ = atan2(y_, x_);  // atan2()先y后x
	}
	void Vector::set_x()
	{
		x_ = mag_ * sin(ang_);
	}
	void Vector::set_y()
	{
		y_ = mag_ * cos(ang_);
	}
	// 公有方法定义
	Vector::Vector()  // 默认构造函数
	{
		x_ = y_ = mag_ = ang_ = 0;
		mode_ = RECT;
	}
	Vector::Vector(double n1, double n2, Mode form)  // 带参数的构造函数,默认为直角坐标表示方式
	{
		// 获取初始化模型
		mode_ = form;
		if (mode_ == RECT)  // 直角形式
		{
			x_ = n1;
			y_ = n2;
			set_mag();
			set_ang();
		}
		else if (mode_ == POL)
		{
			mag_ = n1;
			ang_ = n2 / Rad_to_Deg;  // 以度数输入,转换为弧度存储
			set_x();
			set_y();
		}
		else
		{
			cout << "没有这个模型,按照默认构造函数初始化。" << endl;
			x_ = y_ = mag_ = ang_ = 0;
			mode_ = RECT;
		}
	}
	void Vector::reset(double n1, double n2, Mode form)
	{
		// 获取初始化模型
		mode_ = form;
		if (mode_ == RECT)  // 直角形式
		{
			x_ = n1;
			y_ = n2;
			set_mag();
			set_ang();
		}
		else if (mode_ == POL)
		{
			mag_ = n1;
			ang_ = n2 / Rad_to_Deg;  // 以度数输入,转换为弧度存储
			set_x();
			set_y();
		}
		else
		{
			cout << "没有这个模型,按照默认构造函数初始化。" << endl;
			x_ = y_ = mag_ = ang_ = 0;
			mode_ = RECT;
		}
	}
	Vector::~Vector()  // 析构函数
	{
	}
	void Vector::polar_mode()  // 使用POL坐标
	{
		mode_ = POL;
	}
	void Vector::rect_mode()  // 使用RECT坐标
	{
		mode_ = RECT;
	}
	// 运算符重载
	Vector Vector::operator+(const Vector& v) const
	{
		return Vector(x_ + v.x_, y_ + v.y_);
	}
	Vector Vector::operator-(const Vector& v) const
	{
		return Vector(x_ - v.x_, y_ - v.y_);
	}
	Vector Vector::operator-() const {
		return Vector(-x_, -y_);
	}
	Vector Vector::operator*(double n) const
	{
		return Vector(n * x_, n * y_);
	}
	// 友元
	Vector operator*(double n, const Vector& v)
	{
		return v * n;
	}
	ostream& operator<<(ostream& os, const Vector& v)
	{
		if (v.mode_ == Vector::RECT)
		{
			os << "(x, y) = " << "(" << v.x_
				<< ", " << v.y_ << ")" << endl;
		}
		else if (v.mode_ == Vector::POL)
		{
			os << "(m, a) = " << "(" << v.mag_
				<< ", " << v.ang_ << ")" << endl;
		}
		else
		{
			os << "没有这个形式.\n";
		}
		return os;
	}
}
 
运行结果
 
2. 对Vector类的头文件(程序清单11.13)和实现文件(程序清单11.14)进行修改,使其不再存储向量的长度和角度,而在调用magval()和angval()时计算它们。应保留公有接口不变(公有方法及其参数不变),但对私有部分(包括一些私有方法)和方法进行修改。然后,使用程序清单11.15对修改后的版本进行测试,结果应该与以前相同,因为Vector类的公有接口与原来相同。
答:删除私有成员变量mag和ang,删除私有成员函数set_mag()和set_ang(),修改私有成员函数set_x()和set_y()。修改公有成员函数中所有涉及mag和ang的函数。
Vector2.h头文件
#pragma once
// 头文件
#include <iostream>
// using 声明
using std::cout;
using std::endl;
// 名称空间VECTOR
namespace VECTOR
{
	// using 声明
	using std::ostream;
	// Vector类声明
	class Vector
	{
	public:
		enum Mode { RECT, POL };
		// RECT表示直角坐标,POL表示极坐标
	private:
		double x_;  // 横坐标
		double y_;  // 纵坐标
		Mode mode_;  
	public:
		// 公有方法声明
		Vector();  // 默认构造函数
		Vector(double n1, double n2, Mode form = RECT);  // 带参数的构造函数,默认为直角坐标表示方式
		void reset(double n1, double n2, Mode form = RECT);
		~Vector();  // 析构函数
		void set_x(double mag, double ang);
		void set_y(double mag, double ang);
		double xval() const { return x_; }
		double yval() const { return y_; }
		double magval() const;
		double angval() const;
		void polar_mode();  // 使用POL坐标
		void rect_mode();  // 使用RECT坐标
		// 运算符重载
		Vector operator+(const Vector& v) const;
		Vector operator-(const Vector& v) const;
		Vector operator-() const;
		Vector operator*(double n) const;
		// 友元
		friend Vector operator*(double n, const Vector& v);
		friend ostream& operator<<(ostream& os, const Vector& v);
	};
}
 
main2.cpp测试文件
// 头文件
#include "Vector2.h"
#include <ctime>
#include <cstdlib>
// using 编译指令
using VECTOR::Vector;
// using 声明
using std::cin;
int main()
{
	// 所需变量
	Vector result(0.0, 0.0);  // 存储每一步的结果
	double distance;  // 距离
	double step;  // 步长
	double steps = 0;  // 步数
	// 设置随机数种子
	srand((unsigned)time(0));
	// 输入目标距离
	cout << "Enter target distance (q to quit): ";
	while (cin >> distance)
	{
		// 输入步长
		cout << "Enter step length: ";
		if (!(cin >> step))
			break;
		// 计算
		while (result.magval() < distance)
		{
			double angle = rand() % 360;
			Vector tmp(step, angle, Vector::POL);
			result = result + tmp;
			++steps;
		}
		// 按格式输出
		cout << "After " << steps << "steps, the subject has the following location:\n";
		cout << result;
		result.polar_mode();
		cout << "or\n" << result;
		cout << "Average outward distance per step = " << distance / steps << endl;
		// 重置数据
		steps = 0;
		result.reset(0.0, 0.0);
		// 下一组
		cout << "Enter target distance (q to quit): ";
	}
	return 0;
}
 
Vector2.cpp方法定义文件
// 头文件
#include "Vector2.h"
#include <cmath>
// using 声明
using std::sqrt;
using std::sin;
using std::cos;
using std::atan;
using std::atan2;
// 名称空间VECTOR
namespace VECTOR
{
	// 符号常量
	const double Rad_to_Deg = 45.0 / atan(1.0);  // 1弧度转度
	// 公有方法定义
	Vector::Vector()  // 默认构造函数
	{
		x_ = y_ = 0;
		mode_ = RECT;
	}
	Vector::Vector(double n1, double n2, Mode form)  // 带参数的构造函数,默认为直角坐标表示方式
	{
		// 获取初始化模型
		mode_ = form;
		if (mode_ == RECT)  // 直角形式
		{
			x_ = n1;
			y_ = n2;
		}
		else if (mode_ == POL)
		{
			set_x(n1, n2 / Rad_to_Deg);
			set_y(n1, n2 / Rad_to_Deg);
		}
		else
		{
			cout << "没有这个模型,按照默认构造函数初始化。" << endl;
			x_ = y_ = 0;
			mode_ = RECT;
		}
	}
	void Vector::reset(double n1, double n2, Mode form)
	{
		// 获取初始化模型
		mode_ = form;
		if (mode_ == RECT)  // 直角形式
		{
			x_ = n1;
			y_ = n2;
		}
		else if (mode_ == POL)
		{
			set_x(n1, n2 / Rad_to_Deg);
			set_y(n1, n2 / Rad_to_Deg);
		}
		else
		{
			cout << "没有这个模型,按照默认构造函数初始化。" << endl;
			x_ = y_ = 0;
			mode_ = RECT;
		}
	}
	Vector::~Vector()  // 析构函数
	{
	}
	double Vector::magval() const
	{
		return sqrt(x_ * x_ + y_ * y_);
	}
	double Vector::angval() const
	{
		if (x_ == 0 && y_ == 0)
			return 0;
		else
			return atan2(y_, x_);
	}
	void Vector::set_x(double mag, double ang)
	{
		x_ = mag * cos(ang);
	}
	void Vector::set_y(double mag, double ang)
	{
		y_ = mag * sin(ang);
	}
	void Vector::polar_mode()  // 使用POL坐标
	{
		mode_ = POL;
	}
	void Vector::rect_mode()  // 使用RECT坐标
	{
		mode_ = RECT;
	}
	// 运算符重载
	Vector Vector::operator+(const Vector& v) const
	{
		return Vector(x_ + v.x_, y_ + v.y_);
	}
	Vector Vector::operator-(const Vector& v) const
	{
		return Vector(x_ - v.x_, y_ - v.y_);
	}
	Vector Vector::operator-() const {
		return Vector(-x_, -y_);
	}
	Vector Vector::operator*(double n) const
	{
		return Vector(n * x_, n * y_);
	}
	// 友元
	Vector operator*(double n, const Vector& v)
	{
		return v * n;
	}
	ostream& operator<<(ostream& os, const Vector& v)
	{
		if (v.mode_ == Vector::RECT)
		{
			os << "(x, y) = " << "(" << v.x_
				<< ", " << v.y_ << ")" << endl;
		}
		else if (v.mode_ == Vector::POL)
		{
			os << "(m, a) = " << "(" << v.magval()
				<< ", " << v.angval() * Rad_to_Deg << ")" << endl;
		}
		else
		{
			os << "没有这个形式.\n";
		}
		return os;
	}
}
 
3. 修改程序清单11.15,使之报告N次测试中最高、最低和平均步数(其中N是用户输入的整数),而不是报告每次测试的结果。
答:
// 头文件
#include <iostream>
#include <cstdlib>
#include <ctime>
#include "Vector1.h"
int main()
{
	// using 编译指令
	using namespace std;
	// using 声明
	using VECTOR::Vector;
	// 设置随机数种子
	srand((unsigned)time(0));
	// 所需变量
	Vector result(0.0, 0.0);  // 存储每一步的结果
	unsigned long steps = 0;  // 步数
	double step; // 步长
	double target;  // 目标距离
	int max = 0;  // 最高步数
	int min = 0;  // 最低步数
	int sum = 0;  // 总步数
	int times = 0;  // 测试次数
	double average = 0;  // 平均步数
	// 输入
	cout << "Enter target distance (q to quit): ";
	while (cin >> target)
	{
		cout << "Enter step length: ";
		if (!(cin >> step))
			break;
		// 计算
		while (result.magval() < target)
		{
			double angle = rand() % 360;
			Vector tmp(step, angle, Vector::POL);
			result = result + tmp;
			++steps;
		}
		// 按格式输出
		cout << "After " << steps << " steps, the subject "
			<< "has the following location:\n";
		cout << result << endl;
		result.polar_mode();
		cout << "or\n";
		cout << result << endl;
		cout << "Average outward distance per step = "
			<< result.magval() / steps << endl;
		// 比较与统计
		if (steps > max)
			max = steps;
		if (min == 0 || steps < min)
			min = steps;
		sum += steps;
		++times;
		// 重置,下一组
		steps = 0;
		result.reset(0.0, 0.0);
		cout << "Enter target distance (q to quit): ";
	}
	cout << "测试次数: " << times << endl;
	cout << "最高步数: " << max << endl;
	cout << "最低步数: " << min << endl;
	cout << "平均步数: " << (double)sum / times << endl;
	cout << "Bye!\n";
	return 0;
}
 
4. 重新编写最后的Time类示例(程序清单11.10、程序清单11.11和程序清单11.12),使用友元函数来实现所有的重载运算符。
答:把原来的成员函数运算符重载用友元来实现。
Time.h头文件
#pragma once
// 头文件
#include <iostream>
// using 声明
using std::cout;
using std::endl;
// Time类声明
class Time
{
private:
	int hours_;  // 小时数
	int minutes_;  // 分钟数
public:
	Time();  // 默认构造函数
	Time(int h, int m);
	void AddMin(int m);
	void AddHr(int h);
	// 新友元
	friend Time operator+(const Time& t1, const Time& t2);
	friend Time operator-(const Time& t1, const Time& t2);
	friend Time operator*(const Time& t1, double n);
	// 原友元
	friend Time operator*(double n, const Time& t) { return t * n; }
	friend std::ostream& operator<<(std::ostream& os, const Time& t);
};
 
main4.cpp测试文件
// 头文件
#include "Time.h"
int main()
{
	Time aida(3, 35);
	Time tosca(2, 48);
	Time temp;
	cout << "Aida and Tosca:\n";
	cout << aida << "; " << tosca << endl;
	temp = aida + tosca;
	cout << "Aida + Tosca: " << temp << endl;
	temp = aida * 1.17;
	cout << "Aida * 1.17: " << temp << endl;
	cout << "10.0 * Tosca: " << 10.0 * tosca << endl;
	return 0;
}
 
Time.cpp方法定义文件
// 头文件
#include "Time.h"
Time::Time()  // 默认构造函数
{
	hours_ = minutes_ = 0;
}
Time::Time(int h, int m)
{
	hours_ = h;
	minutes_ = m;
}
void Time::AddMin(int m)
{
	minutes_ += m;
	hours_ = minutes_ / 60;
	minutes_ %= 60;
}
void Time::AddHr(int h)
{
	hours_ += h;
}
// 新友元
Time operator+(const Time& t1, const Time& t2)
{
	int sum_m = t1.minutes_ + t2.minutes_;
	int sum_h = t1.hours_ + t2.hours_ + sum_m / 60;
	sum_m %= 60;
	return Time(sum_h, sum_m);
}
Time operator-(const Time& t1, const Time& t2)
{
	int sum_m = t1.minutes_ - t2.minutes_ + (t1.hours_ - t2.hours_) * 60;
	int sum_h = sum_m / 60;
	sum_m %= 60;
	return Time(sum_h, sum_m);
}
Time operator*(const Time& t1, double n)
{
	int sum_m = t1.hours_ * 60 * n + t1.minutes_ * n;
	return Time(sum_m / 60, sum_m % 60);
}
// 原友元
std::ostream& operator<<(std::ostream& os, const Time& t)
{
	os << t.hours_ << " hours, " << t.minutes_ << "minutes.";
	return os;
}
 
5. 重新编写Stonewt类(程序清单11.16和程序清单11.17),使它有一个状态成员,由该成员来控制对象应转换为英石格式、整数磅格式还是浮点磅格式。重载运<<运算符,使用它来替换show_stn()和show_lbs()方法。重载加法、减法和乘法运算符,以便可以对Stonewt值进行加、减、乘运算。编写一个使用所有类方法和友元的小程序来测试这个类。
答:
 Stonewt.h头文件
#pragma once
// 头文件
#include <iostream>
// Stonewt类声明
class Stonewt
{
public:
	enum Style {STONE, POUNDS, FPOUNDS};
private:
	enum {Lbs_per_stn = 14};
	int stone;
	double pds_left;
	double pounds;
	Style style;
public:
	Stonewt();
	Stonewt(double lbs);
	Stonewt(int stn, double lbs);
	~Stonewt() { };
	void set_style(Style s);
	// 运算符重载
	Stonewt operator+(const Stonewt& s) const;
	Stonewt operator-(const Stonewt& s) const;
	Stonewt operator*(double n) const;
	// 友元
	friend std::ostream& operator<<(std::ostream& os, const Stonewt& s);
};
 
main5.cpp测试文件
// 头文件
#include "Stonewt.h"
// using 声明
using std::cout;
using std::endl;
int main()
{
	Stonewt incognito = 275;
	cout << "incognito: " << incognito << endl;
	Stonewt wolfe(287.5);
	cout << "wolfe: " << wolfe << endl;
	Stonewt taft(21, 8);
	cout << "taft: " << taft << endl;
	incognito = 276.8;
	cout << "incognito: " << incognito << endl;
	cout << "wolfe: " << wolfe * 2.3 << endl;
	taft = incognito + wolfe + 200;
	cout << "taft: " << taft << endl;
	wolfe.set_style(Stonewt::FPOUNDS);
	wolfe = wolfe * 2.3;
	cout << "wolfe: " << wolfe << endl;
	return 0;
}
 
Stonewt.cpp方法定义文件
// 头文件
#include "Stonewt.h"
Stonewt::Stonewt()
{
	stone = pounds = pds_left = 0;
	style = STONE;
}
Stonewt::Stonewt(double lbs)
{
	stone = int(lbs) / Lbs_per_stn;
	pds_left = int(lbs) % Lbs_per_stn + lbs - int(lbs);
	pounds = lbs;
	style = FPOUNDS;
}
Stonewt::Stonewt(int stn, double lbs)
{
	stone = stn;
	pds_left = lbs;
	pounds = stn * Lbs_per_stn + lbs;
	style = FPOUNDS;
}
void Stonewt::set_style(Style s)
{
	style = s;
}
// 运算符重载
Stonewt Stonewt::operator+(const Stonewt& s) const
{
	Stonewt tmp;
	tmp.pounds = pounds + s.pounds;
	tmp.stone = tmp.pounds / Lbs_per_stn;
	tmp.pds_left = (int)tmp.pounds % Lbs_per_stn + tmp.pounds - (int)tmp.pounds;
	tmp.style = this->style;
	return tmp;
}
Stonewt Stonewt::operator-(const Stonewt& s) const
{
	Stonewt tmp;
	tmp.pounds = pounds - s.pounds;
	tmp.stone = tmp.pounds / Lbs_per_stn;
	tmp.pds_left = (int)tmp.pounds % Lbs_per_stn + tmp.pounds - int(tmp.pounds);
	tmp.style = this->style;
	return tmp;
}
Stonewt Stonewt::operator*(double n) const
{
	Stonewt tmp;
	tmp.pounds = pounds * n;
	tmp.stone = tmp.pounds / Lbs_per_stn;
	tmp.pds_left = int(tmp.pounds) / Lbs_per_stn + tmp.pounds - (int)tmp.pounds;
	tmp.style = this->style;
	return tmp;
}
// 友元
std::ostream& operator<<(std::ostream& os, const Stonewt& s)
{
	if (s.style == Stonewt::STONE)
	{
		double st = s.stone + s.pds_left / Stonewt::Lbs_per_stn;
		os << st << "stone\n";
	}
	else if (s.style == Stonewt::POUNDS)
	{
		os << s.pounds << "pounds\n";
	}
	else
	{
		os << s.stone << "stone, " << s.pds_left << "pounds\n";
	}
	return os;
}
 
6. 重新编写Stonewt类(程序清单11.16和程序清单11.17),重载6个关系运算符。运算对pounds成员进行比较,并返回一个布尔值。编写一个程序,他声明一个包含6个Stonewt对象的数组,并在数组声明中初始化前3个对象。然后使用循环来读取用于设置剩余的三个数组元素的值。接着报告最小的元素、最大的元素以及大于或等于11英石的元素的数量(最简单的方法是创建一个Stonewt对象,并将其初始化为11英石,然后将该对象同其他对象进行比较)。
答:
 Stonewt1.h头文件
#pragma once
// 头文件
#include <iostream>
// Stonewt类声明
class Stonewt
{
private:
	enum {Lbs_per_stn = 14};
	int stone;
	double pds_left;
	double pounds;
public:
	Stonewt(double lbs);
	Stonewt(int stn, double lbs);
	Stonewt();
	~Stonewt();
	// 关系运算符重载
	bool operator<(const Stonewt& s) const;
	bool operator<=(const Stonewt& s) const;
	bool operator>(const Stonewt& s) const;
	bool operator>=(const Stonewt& s) const;
	bool operator==(const Stonewt& s) const;
	bool operator!=(const Stonewt& s) const;
	void show_lbs() const;
	void show_stn() const;
};
 
main6.cpp测试文件
// 头文件
#include "Stone1.h"
// 符号常量
const int SIZE = 6;
// using 声明
using std::cin;
using std::cout;
using std::endl;
int main()
{
	Stonewt stone_arr[SIZE] = { 253.6, Stonewt(8, 0.35), Stonewt(23, 0) };
	double input;
	Stonewt eleven = Stonewt(11, 0.0);
	Stonewt max = stone_arr[0];
	Stonewt min = stone_arr[0];
	int num = 0;
	for (int i = 3; i < SIZE; ++i)
	{
		cout << "enter the No." << i + 1 << "'s element info(int pounds): ";
		cin >> input;
		stone_arr[i] = Stonewt(input);
		while (cin.get() != '\n')
			continue;
	}
	for (int i = 0; i < SIZE; ++i)
	{
		if (max < stone_arr[i]) max = stone_arr[i];
		if (min > stone_arr[i]) min = stone_arr[i];
		if (stone_arr[i] > eleven)
			++num;
	}
	cout << "The weight max: ";
	max.show_stn();
	cout << "\nThe weight min: ";
	min.show_stn();
	cout << "\nHeavy than eleven: " << num << endl;
	return 0;
}
 
Stonewt1.cpp方法定义文件
// 头文件
#include "Stone1.h"
// using 声明
using std::cout;
using std::endl;
Stonewt::Stonewt(double lbs)
{
	stone = (int)lbs / Lbs_per_stn;
	pds_left = (int)lbs % Lbs_per_stn + lbs - int(lbs);
	pounds = lbs;
}
Stonewt::Stonewt(int stn, double lbs)
{
	stone = stn;
	pds_left = lbs;
	pounds = stn * Lbs_per_stn + lbs;
}
Stonewt::Stonewt()
{
	stone = pounds = pds_left = 0;
}
Stonewt::~Stonewt()
{
}
// 关系运算符重载
bool Stonewt::operator<(const Stonewt& s) const
{
	return pounds < s.pounds;
}
bool Stonewt::operator<=(const Stonewt& s) const
{
	return pounds <= s.pounds;
}
bool Stonewt::operator>(const Stonewt& s) const
{
	return pounds > s.pounds;
}
bool Stonewt::operator>=(const Stonewt& s) const
{
	return pounds >= s.pounds;
}
bool Stonewt::operator==(const Stonewt& s) const
{
	return pounds == s.pounds;
}
bool Stonewt::operator!=(const Stonewt& s) const
{
	return pounds != s.pounds;
}
void Stonewt::show_lbs() const
{
	cout << stone << "stone, " << pds_left << "pounds\n";
}
void Stonewt::show_stn() const
{
	cout << pounds << "pounds\n";
}
 
7. 按要求实现一个复数类(complex)…。
答:
 complex.h头文件
#pragma once
// 头文件
#include <iostream>
// complex类声明
class complex
{
private:
	double real;  // 实部
	double imaginary;  // 虚部
public:
	complex(double a = 0, double b = 0);  // 默认构造函数
	~complex();  // 析构函数
	// 运算符重载
	complex operator~() const;
	complex operator+(const complex& c) const;
	complex operator-(const complex& c) const;
	complex operator*(const complex& c) const;
	complex operator*(double n) const;
	// 友元
	friend complex operator*(double n, const complex& c) { return c * n; }
	friend std::ostream& operator<<(std::ostream& os, const complex& c);
	friend std::istream& operator>>(std::istream& is, complex& c);
};
 
main7.cpp测试文件
// 头文件
#include "complex.h"
// using 声明
using std::cin;
using std::cout;
using std::endl;
int main()
{
	complex a(3.0, 4.0);
	complex c;
	cout << "Enter a complex number (q to quit):\n";
	while (cin >> c)
	{
		cout << "c is " << c << endl;
		cout << "complex conjugate is " << ~c << endl;
		cout << "a is " << a << endl;
		cout << "a + c is " << a + c << endl;
		cout << "a - c is " << a - c << endl;
		cout << "a * c is" << a * c << endl;
		cout << "2 * c is " << 2 * c << endl;
		cout << "Enter a complex number (q to quit):\n";
 	}
	cout << "Done!\n";
	return 0;
}
 
complex.cpp方法定义文件
// 头文件
#include "complex.h"
// using 声明
using std::cout;
complex::complex(double a, double b)  // 默认构造函数
{
	real = a;
	imaginary = b;
}
complex::~complex()  // 析构函数
{
}
// 运算符重载
complex complex::operator~() const
{
	return complex(real, -imaginary);
}
complex complex::operator+(const complex& c) const
{
	return complex(real + c.real, imaginary + c.imaginary);
}
complex complex::operator-(const complex& c) const
{
	return complex(real - c.real, imaginary - c.imaginary);
}
complex complex::operator*(const complex& c) const
{
	int a = real * c.real - imaginary * c.imaginary;
	int b = real * c.imaginary + imaginary * c.real;
	return complex(a, b);
}
complex complex::operator*(double n) const
{
	return complex(real * n, imaginary * n);
}
// 友元
std::ostream& operator<<(std::ostream& os, const complex& c)
{
	os << "(" << c.real << "," << c.imaginary << "i)";
	return os;
}
std::istream& operator>>(std::istream& is, complex& c)
{
	cout << "real: ";
	if (!(is >> c.real))
		return is;
	cout << "imaginary: ";
	is >> c.imaginary;
	return is;
}
 
程序运行结果
 



















