《C++ Primer Plus》第十一章复习题和编程练习

news2024/10/6 1:44:41

这里写目录标题

  • 一、复习题
  • 二、编程练习

一、复习题

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;
}

程序运行结果
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1698253.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python语言基础学习(下)

目录 一、顺序语句 二、条件语句 (1) if (2) if - else (3) if - elif - else 缩进和代码块 空语句 pass 三、循环语句 while 循环 for 循环 continue break 四、函数 创建函数 调用函数 函数返回 函数变量 函数递归 关键字参数 五、列表和元组 创建列表 …

创新实训2024.05.25日志:Web应用技术选型

我们的web应用使用python web的fastapi框架&#xff0c;通过uvicorn开启web服务。 1. refs 官网文档&#xff1a;FastAPI (tiangolo.com) github&#xff1a;https://github.com/tiangolo/fastapi 2. 环境配置 python:3.11 uvicorn:0.29.0 pip install "uvicorn[stan…

【启程Golang之旅】基本变量与类型讲解

欢迎来到Golang的世界&#xff01;在当今快节奏的软件开发领域&#xff0c;选择一种高效、简洁的编程语言至关重要。而在这方面&#xff0c;Golang&#xff08;又称Go&#xff09;无疑是一个备受瞩目的选择。在本文中&#xff0c;带领您探索Golang的世界&#xff0c;一步步地了…

嵌入式全栈开发学习笔记---C语言笔试复习大全25(实现学生管理系统)

目录 实现学生管理系统 第一步&#xff1a;结构体声明 第二步&#xff1a;重命名结构体 第三步&#xff1a;限定可以存储的最大学生数目 第四步&#xff1a;定义结构体指针数组和定义一个整型变量存放当前的人数 第五步&#xff1a;设计欢迎界面 第六步&#xff1a;设计…

【设计模式】JAVA Design Patterns——Command(事务模式)

&#x1f50d;目的 将请求封装为对象&#xff0c;从而使你可以将具有不同请求的客户端参数化&#xff0c;队列或记录请求&#xff0c;并且支持可撤销操作。 &#x1f50d;解释 真实世界例子 有一个巫师在地精上施放咒语。咒语在地精上一一执行。第一个咒语使地精缩小&#xff0…

从关键新闻和最新技术看AI行业发展(2024.5.6-5.19第二十三期) |【WeThinkIn老实人报】

写在前面 【WeThinkIn老实人报】旨在整理&挖掘AI行业的关键新闻和最新技术&#xff0c;同时Rocky会对这些关键信息进行解读&#xff0c;力求让读者们能从容跟随AI科技潮流。也欢迎大家提出宝贵的优化建议&#xff0c;一起交流学习&#x1f4aa; 欢迎大家关注Rocky的公众号&…

C++之std::is_trivially_copyable(平凡可复制类型检测)

目录 1.C基础回顾 1.1.平凡类型 1.2.平凡可复制类型 1.3.标准布局类型 2.std::is_trivially_copyable 2.1.定义 2.2.使用 2.3.总结 1.C基础回顾 在C11中&#xff0c;平凡类型&#xff08;Trivial Type&#xff09;、平凡可复制类型&#xff08;TrivialCopyable&#x…

深入理解与防御跨站脚本攻击(XSS):从搭建实验环境到实战演练的全面教程

跨站脚本攻击&#xff08;XSS&#xff09;是一种常见的网络攻击手段&#xff0c;它允许攻击者在受害者的浏览器中执行恶意脚本。以下是一个XSS攻击的实操教程&#xff0c;包括搭建实验环境、编写测试程序代码、挖掘和攻击XSS漏洞的步骤。 搭建实验环境 1. 安装DVWA&#xff…

8.什么是HOOK

程序编译的本质是&#xff0c;首先计算机它只能看得懂机器码也就是只能看得懂数字&#xff0c;机器码学起来很费劲然后就创造了编译器这个东西&#xff0c;编译器它懂机器语言所以它可以跟机器沟通&#xff0c;而我们人可以跟编译器沟通&#xff0c;人跟编译器的语言就是各种各…

GBDT、XGBoost、LightGBM算法详解

文章目录 一、GBDT (Gradient Boosting Decision Tree) 梯度提升决策树1.1 回归树1.2 梯度提升树1.3 Shrinkage1.4 调参1.5 GBDT的适用范围1.6 优缺点 二、XGBoost (eXtreme Gradient Boosting)2.1 损失函数2.2 正则项2.3 打分函数计算2.4 分裂节点2.5 算法过程2.6 参数详解2.7…

不拍视频,不直播怎么在视频号卖货赚钱?开一个它就好了!

大家好&#xff0c;我是电商糖果 视频号这两年看着抖音卖货的热度越来越高&#xff0c;也想挤进电商圈。 于是它模仿抖音推出了自己的电商平台——视频号小店。 只要商家入驻视频号小店&#xff0c;就可以在视频号售卖商品。 具体怎么操作呢&#xff0c;需要拍视频&#xf…

leedcode【142】. 环形链表 II——Java解法

Problem: 142. 环形链表 II 思路解题方法复杂度Code性能 思路 1.用快慢指针找到相遇的点&#xff08;快指针一次走一步&#xff0c;慢指针一次走两步&#xff09; 2.一个指针从head开始&#xff0c;一个指针从相遇点开始&#xff0c;一次一步&#xff0c;相遇处即为环入口 解题…

Vmware 17安装 CentOS9

前言 1、提前下载好需要的CentOS9镜像&#xff0c;下载地址&#xff0c;这里下载的是x86_64 2、提前安装好vmware 17&#xff0c;下载地址 &#xff0c;需要登录才能下载 安装 1、创建新的虚拟机 2、在弹出的界面中选择对应的类型&#xff0c;我这里选择自定义&#xff0c;点…

P459 包装类Wrapper

包装类的分类 1&#xff09;针对八种基本数据类型相应的引用类型——包装类。 2&#xff09;有了类的特点&#xff0c;就可以调用类中的方法。 Boolean包装类 Character包装类 其余六种Number类型的包装类 包装类和基本数据类型的相互转换 public class Integer01 {publi…

【大数据面试题】32 Flink 怎么重复读 Kafka?

一步一个脚印&#xff0c;一天一道面试题 首先&#xff0c;为什么要读过的 Kafka 数据重写读一次呢&#xff1f;什么场景下要怎么做呢&#xff1f; 答&#xff1a;当任务失败&#xff0c;从检查点Checkpoint 开始重启时&#xff0c;检查点的数据是之前的了&#xff0c;就需要…

从 0 开始实现一个网页聊天室 (小型项目)

实现功能 用户注册和登录好友列表展示会话列表展示: 显示当前正在进行哪些会话 (单聊 / 群聊) , 选中好友列表中的某个好友, 会生成对应的会话实时通信, A给B发送消息, B的聊天界面 / 会话界面能立刻显示新的消息 TODO: 添加好友功能用户头像显示传输图片 / 表情包历史消息搜…

CTF之Web_python_block_chain

这种题对于我来说只能看大佬的wp&#xff08;但是这一题是wp都看不懂&#xff0c;只能表达一下我的理解了&#xff09; &#xff08;最后有简单方法&#xff0c;前面一种没看懂没关系&#xff09; 下面这一部分是首页的有用部分 访问/source_code,得到源码&#xff1a; # -*-…

鸿蒙 DevEco Studio 3.1 Release 下载sdk报错的解决办法

鸿蒙 解决下载SDK报错的解决方法 最近在学习鸿蒙开发&#xff0c;以后也会记录一些关于鸿蒙相关的问题和解决方法&#xff0c;希望能帮助到大家。 总的来说一般有下面这样的报错 报错一&#xff1a; Components to install: - ArkTS 3.2.12.5 - System-image-phone 3.1.0.3…

企业客户信息反馈|基于SprinBoot+vue的企业客户信息反馈平台(源码+数据库+文档)

企业客户信息反馈平台 目录 基于SprinBootvue的企业客户信息反馈平台 一、前言 二、系统设计 三、系统功能设计 1平台功能模块 2后台登录 5.2.1管理员功能 5.2.2客户功能 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&am…

AIGC 005-Dreambooth定制化生成,微调文本到图像的扩散模型!

AIGC 005-Dreambooth定制化生成&#xff0c;微调文本到图像的扩散模型&#xff01; 文章目录 0 论文工作1 论文方法2 效果 0 论文工作 DreamBooth 论文 (DreamBooth: Fine-Tuning Text-to-Image Diffusion Models for Subject-Driven Generation) 提出了一种新颖的技术&#x…