这里写目录标题
- 一、复习题
- 二、编程练习
一、复习题
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;
}
程序运行结果