目录
11.1
// class.h
#pragma once
#ifndef _CLASS_H_
#define _ClASS_H_
#include<iostream>
namespace VECTOR
{
class Vector
{
public:
enum Mode { 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); //默认模式为RECT
void reset(double n1, double n2, Mode form = RECT);
~Vector();
//之所以要设置xval, yval, magval, angval这些函数,而不是将这些值存放在private区域中,就是为了在main函数中可以调用这些函数来获得这些值,若在private空间中则无法访问
double xval() const // xvalue
{
return x;
}
double yval() const //yvalue;
{
return y;
}
double magval() const //magvalue
{
return mag;
}
double angval() const //angvalue
{
return ang;
}
void polar_mode(); //切换为polar mode
void rect_mode(); //切换为rect mode
// 重载运算符:
Vector operator+(const Vector& b)const;
Vector operator-(const Vector& b)const;
Vector operator-()const;
Vector operator*(double n)const;
// 友元函数:
friend Vector operator*(double n, const Vector& a);
friend std::ostream& operator<<(std::ostream& os, const Vector& v);
};
}
#endif
// fuc.cpp
#include"class.h"
#include<cmath> // 使用了 sqrt()求根号值函数,tan() 接受角度值返回斜率值, atan() 接受斜率值返回角度值, sin和cos接受角度值分别返回各自的正弦值和余弦值
using std::cout;
using std::sqrt;
using std::tan;
using std::atan;
using std::cos;
using std::sin;
using std::endl;
namespace VECTOR
{
const double Rad_to_deg = 45 / atan(1.0); // 电脑中一弧度所代表的角度
void Vector::set_mag()
{
mag = sqrt(x * x + y * y);
}
void Vector::set_ang()
{
if (x == 0 && y == 0)
{
ang = 0.0;
}
else
{
ang = atan2(y, x); // atan2接受两个参数--x和y坐标,更加准确
}
}
void Vector::set_x()
{
x = mag * cos(ang);
}
void Vector::set_y()
{
y = mag * sin(ang);
}
Vector::Vector()
{
x = y = mag = ang = 0.0;
mode = RECT; // 默认模式为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;
set_x();
set_y();
}
else
{
cout << "Incorrect 3rd argument to Vector() -- ";
cout << "Vector set to 0" << endl;
x = y = mag = ang = 0.0;
mode = RECT;
}
}
void Vector::reset(double n1, double n2, Mode form)
{
mode = form;
if (mode == RECT) // 根据x和y来设置距离和方向
{
x = n1;
y = n2;
set_mag();
set_ang();
}
else if (mode == POL) // 根据距离和方向来设置x和y
{
mag = n1;
ang = n2;
set_x();
set_y();
}
else
{
cout << "Incorrect 3rd argument to Vector() -- ";
cout << "Vector set to 0" << endl;
x = y = mag = ang = 0.0;
mode = RECT;
}
}
Vector::~Vector()
{
//析构函数
}
void Vector::polar_mode()
{
mode = POL;
}
void Vector::rect_mode()
{
mode = RECT;
}
Vector Vector::operator+(const Vector& b)const
{
return Vector(x + b.x, y + b.y); // 构造函数在运行时会自动创建一个临时的类对象来进行一系列的赋值,直接return一个构造函数的调用相当于return一个设置好值的类对象
}
Vector Vector::operator-(const Vector& b)const //实现类对象值的相减
{
return Vector(x - b.x, y - b.y);
}
Vector Vector::operator-()const //实现类对象的值变为相反数
{
return Vector(-x, -y);
}
Vector Vector::operator*(double n)const
{
return Vector(x * n, y * n);
}
//友元函数的定义(无需再加上friend,同时也无需再声明是类中的函数)
Vector operator*(double n, const Vector& a)
{
return a * n;
}
std::ostream& operator<<(std::ostream& os, const Vector& v) // 返回值为 ostream& 即 ostream流的一个引用
{
// 因为是友元函数,所以不在类作用域中,不可以直接使用属于类作用域的两个枚举量 RECT 和 POL -- VECTOR::Vector::RECT/POL
if (v.mode == Vector::RECT)
{
os << "(x,y) = (" << v.x << ", " << v.y << ")";
}
else if (v.mode == Vector::POL)
{
os << "(m,a)= (" << v.mag << ", "
<< v.ang * Rad_to_deg << ")";
}
else
{
os << "Vector object mode is invalid";
}
return os; // os重载 << 运算符的第一个参数,同时也是一个ostream流的引用
}
}
// main.cpp
//要求: 改写随机漫步程序,将随机漫步的初始条件和结果小结写入文件中
//做法: 利用fstream将数据写入文件中,对 >> 运算符的重载中,可以传入fstream变量参数 -- 并在调用时,将cout换为所创建的fout变量即可
#include"class.h"
#include<cstdlib> // rand() ,srand(),
#include<ctime> //time()
#include<fstream>
int main()
{
using namespace std;
using VECTOR::Vector;
fstream fout; //fout为fstream流变量
fout.open("data.txt"); //打开文件 data.text并将数据传入到该文件中,若没有此文件则创建一个该名字的文件来保存数据
srand(time(0)); //提供随机数种子
double directions;
Vector step;
Vector result(0.0, 0.0);
unsigned long steps = 0;
double target;
double dstep;
cout << "Enter target distance (q to quit): ";
while (cin >> target) //输入数字 -- true 输入字母 -- false
{
cout << "Enter step length: ";
if (!(cin >> dstep)) // 如果输入的不是数字,退出循环
{
break;
}
fout << "Target Distance: " << target << " ," << "Step Size: " << dstep << endl;
while (result.magval() < target) //矢量的长度小于目标长度
{
directions = rand() % 360; //通过随机值来设置下次走的方向
step.reset(dstep, directions, Vector::POL); //修改参数 -- 步子的长度,方向,以及表达方式
result = result + step; // 对象的重载相加
steps++; // 记录一共走了多少步
}
cout << "After " << steps << " steps,the subject has the following location: " << endl;
fout << "After " << steps << " steps,the subject has the following location: " << endl;
cout << result << endl; // 对象的cout显示在屏幕上 ( >>运算符的重载)
fout << result << endl;
result.polar_mode();
cout << "or\n" << result << endl; // 重载 << 运算符的函数中的返回值为 ostream流的一个引用,所以可以连续使用<<运算符
fout << "or\n" << result << endl;
cout << "Average outward distance per step = " << result.magval() / steps << endl;
fout << "Average outward distance per step = " << result.magval() / steps << endl;
steps = 0;
result.reset(0.0, 0.0);
cout << "Enter target distance(q to quit): ";
}
cout << "Bye~" << endl;
//若输入过程中输入了很多字符,则用下面这几行代码来清除,清除完成后即cin,get()!='\n',再结束程序
cin.clear();
while (cin.get() != '\n')
{
continue;
}
system("pause");
return 0;
}
//此题实现了对清单11.15的修改,使一系列数据的同时输入到屏幕上和指定文件中
//修改方式: 主要修改在main函数中
1.增加头文件 #include<fstream>
2.利用fstream创建相应变量: fstream fout
3.利用对应函数打开想要写入数据的文件: fout.open("data.text")
4.利用重载运算符 << 将对象数据传入文件中,即将cout<<对象 变为 fout<<对象(fstream相当于包含在ostream中,所以当参数类型为 ostream&的时候,即可以传入cout,也可以传入fout -- fstream的变量)
11.2
// class.h
#pragma once
#ifndef _CLASS_H_
#define _ClASS_H_
#include<iostream>
namespace VECTOR
{
class Vector
{
public:
enum Mode { 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); //默认模式为RECT
void reset(double n1, double n2, Mode form = RECT);
~Vector();
//之所以要设置xval, yval, magval, angval这些函数,而不是将这些值存放在private区域中,就是为了在main函数中可以调用这些函数来获得这些值,若在private空间中则无法访问
double xval() const // xvalue
{
return x;
}
double yval() const //yvalue;
{
return y;
}
double magval() //magvalue
{
set_mag();
return mag;
}
double angval() //angvalue
{
set_ang();
return ang;
}
void polar_mode(); //切换为polar mode
void rect_mode(); //切换为rect mode
// 重载运算符:
Vector operator+(const Vector& b)const;
Vector operator-(const Vector& b)const;
Vector operator-()const;
Vector operator*(double n)const;
// 友元函数:
friend Vector operator*(double n, const Vector& a);
friend std::ostream& operator<<(std::ostream& os, const Vector& v);
};
}
#endif
// fuc.cpp
#include"class.h"
#include<cmath> // 使用了 sqrt()求根号值函数,tan() 接受角度值返回斜率值, atan() 接受斜率值返回角度值, sin和cos接受角度值分别返回各自的正弦值和余弦值
using std::cout;
using std::sqrt;
using std::tan;
using std::atan;
using std::cos;
using std::sin;
using std::endl;
namespace VECTOR
{
const double Rad_to_deg = 45 / atan(1.0); // 电脑中一弧度所代表的角度
void Vector::set_mag()
{
mag = sqrt(x * x + y * y);
}
void Vector::set_ang()
{
if (x == 0 && y == 0)
{
ang = 0.0;
}
else
{
ang = atan2(y, x); // atan2接受两个参数--x和y坐标,更加准确
}
}
void Vector::set_x()
{
x = mag * cos(ang);
}
void Vector::set_y()
{
y = mag * sin(ang);
}
Vector::Vector()
{
x = y = mag = ang = 0.0;
mode = RECT; // 默认模式为RECT;
}
Vector::Vector(double n1, double n2, Mode form)
{
mode = form;
if (mode == RECT)
{
x = n1;
y = n2;
}
else if (mode == POL)
{
mag = n1;
ang = n2;
set_x();
set_y();
}
else
{
cout << "Incorrect 3rd argument to Vector() -- ";
cout << "Vector set to 0" << endl;
x = y = mag = ang = 0.0;
mode = RECT;
}
}
void Vector::reset(double n1, double n2, Mode form)
{
mode = form;
if (mode == RECT) // 根据x和y来设置距离和方向
{
x = n1;
y = n2;
}
else if (mode == POL) // 根据距离和方向来设置x和y
{
mag = n1;
ang = n2;
set_x();
set_y();
}
else
{
cout << "Incorrect 3rd argument to Vector() -- ";
cout << "Vector set to 0" << endl;
x = y = mag = ang = 0.0;
mode = RECT;
}
}
Vector::~Vector()
{
//析构函数
}
void Vector::polar_mode()
{
mode = POL;
}
void Vector::rect_mode()
{
mode = RECT;
}
Vector Vector::operator+(const Vector& b)const
{
return Vector(x + b.x, y + b.y); // 构造函数在运行时会自动创建一个临时的类对象来进行一系列的赋值,直接return一个构造函数的调用相当于return一个设置好值的类对象
}
Vector Vector::operator-(const Vector& b)const //实现类对象值的相减
{
return Vector(x - b.x, y - b.y);
}
Vector Vector::operator-()const //实现类对象的值变为相反数
{
return Vector(-x, -y);
}
Vector Vector::operator*(double n)const
{
return Vector(x * n, y * n);
}
//友元函数的定义(无需再加上friend,同时也无需再声明是类中的函数)
Vector operator*(double n, const Vector& a)
{
return a * n;
}
std::ostream& operator<<(std::ostream& os, const Vector& v) // 返回值为 ostream& 即 ostream流的一个引用
{
// 因为是友元函数,所以不在类作用域中,不可以直接使用属于类作用域的两个枚举量 RECT 和 POL -- VECTOR::Vector::RECT/POL
if (v.mode == Vector::RECT)
{
os << "(x,y) = (" << v.x << ", " << v.y << ")";
}
else if (v.mode == Vector::POL)
{
os << "(m,a)= (" << v.mag << ", "
<< v.ang * Rad_to_deg << ")";
}
else
{
os << "Vector object mode is invalid";
}
return os; // os重载 << 运算符的第一个参数,同时也是一个ostream流的引用
}
}
// main.cpp
//修改: 程序不再储存矢量的长度和角度,而是在magval()和angval()被调用时计算他们 (保证公有接口不变,对私有部分和方法实现进行修改)
// 原来的magval()和angval()的作用为返回已经储存的mag和ang值,现在的作用为计算这两个值并返回 -- 同时程序不储存这两个值,所以构造函数中不能计算该值
#include"class.h"
#include<cstdlib> // rand() ,srand(),
#include<ctime> //time()
int main()
{
using namespace std;
using VECTOR::Vector;
srand(time(0)); //提供随机数种子
double directions;
Vector step;
Vector result(0.0, 0.0);
unsigned long steps = 0;
double target;
double dstep;
cout << "Enter target distance (q to quit): ";
while (cin >> target) //输入数字 -- true 输入字母 -- false
{
cout << "Enter step length: ";
if (!(cin >> dstep)) // 如果输入的不是数字,退出循环
{
break;
}
while (result.magval() < target) //矢量的长度小于目标长度
{
directions = rand() % 360; //通过随机值来设置下次走的方向
step.reset(dstep, directions, Vector::POL); //修改参数 -- 步子的长度,方向,以及表达方式
result = result + step; // 对象的重载相加
steps++; // 记录一共走了多少步
}
cout << "After " << steps << " steps,the subject has the following location: " << endl;
cout << result << endl; // 对象的cout显示在屏幕上 ( >>运算符的重载)
result.polar_mode();
cout << "or\n" << result << endl; // 重载 << 运算符的函数中的返回值为 ostream流的一个引用,所以可以连续使用<<运算符
cout << "Average outward distance per step = " << result.magval() / steps << endl;
steps = 0;
result.reset(0.0, 0.0);
cout << "Enter target distance(q to quit): ";
}
cout << "Bye~" << endl;
//若输入过程中输入了很多字符,则用下面这几行代码来清除,清除完成后即cin,get()!='\n',再结束程序
cin.clear();
while (cin.get() != '\n')
{
continue;
}
system("pause");
return 0;
}
//修改方式:删去构造函数中的set_mag()和set_ang()函数调用,并将set_mag()的调用加入magval()函数中,set_ang()的调用加入angval()函数中 --- magval()和angval()两个函数的功能从只返回储存的mag和ang值变为设置mag和ang值后再返回这两个值。
11.3
// class.h
#pragma once
#ifndef _CLASS_H_
#define _ClASS_H_
#include<iostream>
namespace VECTOR
{
class Vector
{
public:
enum Mode { 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); //默认模式为RECT
void reset(double n1, double n2, Mode form = RECT);
~Vector();
//之所以要设置xval, yval, magval, angval这些函数,而不是将这些值存放在private区域中,就是为了在main函数中可以调用这些函数来获得这些值,若在private空间中则无法访问
double xval() const // xvalue
{
return x;
}
double yval() const //yvalue;
{
return y;
}
double magval() const //magvalue
{
return mag;
}
double angval() const //angvalue
{
return ang;
}
void polar_mode(); //切换为polar mode
void rect_mode(); //切换为rect mode
// 重载运算符:
Vector operator+(const Vector& b)const;
Vector operator-(const Vector& b)const;
Vector operator-()const;
Vector operator*(double n)const;
// 友元函数:
friend Vector operator*(double n, const Vector& a);
friend std::ostream& operator<<(std::ostream& os, const Vector& v);
};
}
#endif
// fuc.cpp
#include"class.h"
#include<cmath> // 使用了 sqrt()求根号值函数,tan() 接受角度值返回斜率值, atan() 接受斜率值返回角度值, sin和cos接受角度值分别返回各自的正弦值和余弦值
using std::cout;
using std::sqrt;
using std::tan;
using std::atan;
using std::cos;
using std::sin;
using std::endl;
namespace VECTOR
{
const double Rad_to_deg = 45 / atan(1.0); // 电脑中一弧度所代表的角度
void Vector::set_mag()
{
mag = sqrt(x * x + y * y);
}
void Vector::set_ang()
{
if (x == 0 && y == 0)
{
ang = 0.0;
}
else
{
ang = atan2(y, x); // atan2接受两个参数--x和y坐标,更加准确
}
}
void Vector::set_x()
{
x = mag * cos(ang);
}
void Vector::set_y()
{
y = mag * sin(ang);
}
Vector::Vector()
{
x = y = mag = ang = 0.0;
mode = RECT; // 默认模式为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;
set_x();
set_y();
}
else
{
cout << "Incorrect 3rd argument to Vector() -- ";
cout << "Vector set to 0" << endl;
x = y = mag = ang = 0.0;
mode = RECT;
}
}
void Vector::reset(double n1, double n2, Mode form)
{
mode = form;
if (mode == RECT) // 根据x和y来设置距离和方向
{
x = n1;
y = n2;
set_mag();
set_ang();
}
else if (mode == POL) // 根据距离和方向来设置x和y
{
mag = n1;
ang = n2;
set_x();
set_y();
}
else
{
cout << "Incorrect 3rd argument to Vector() -- ";
cout << "Vector set to 0" << endl;
x = y = mag = ang = 0.0;
mode = RECT;
}
}
Vector::~Vector()
{
//析构函数
}
void Vector::polar_mode()
{
mode = POL;
}
void Vector::rect_mode()
{
mode = RECT;
}
Vector Vector::operator+(const Vector& b)const
{
return Vector(x + b.x, y + b.y); // 构造函数在运行时会自动创建一个临时的类对象来进行一系列的赋值,直接return一个构造函数的调用相当于return一个设置好值的类对象
}
Vector Vector::operator-(const Vector& b)const //实现类对象值的相减
{
return Vector(x - b.x, y - b.y);
}
Vector Vector::operator-()const //实现类对象的值变为相反数
{
return Vector(-x, -y);
}
Vector Vector::operator*(double n)const
{
return Vector(x * n, y * n);
}
//友元函数的定义(无需再加上friend,同时也无需再声明是类中的函数)
Vector operator*(double n, const Vector& a)
{
return a * n;
}
std::ostream& operator<<(std::ostream& os, const Vector& v) // 返回值为 ostream& 即 ostream流的一个引用
{
// 因为是友元函数,所以不在类作用域中,不可以直接使用属于类作用域的两个枚举量 RECT 和 POL -- VECTOR::Vector::RECT/POL
if (v.mode == Vector::RECT)
{
os << "(x,y) = (" << v.x << ", " << v.y << ")";
}
else if (v.mode == Vector::POL)
{
os << "(m,a)= (" << v.mag << ", "
<< v.ang * Rad_to_deg << ")";
}
else
{
os << "Vector object mode is invalid";
}
return os; // os重载 << 运算符的第一个参数,同时也是一个ostream流的引用
}
}
// main.cpp
//修改目标: 使程序报告N次测试中的最高,最低和平均步数(N为用户输入的整数),而不是报告每次测试的结果
#include"class.h"
#include<cstdlib> // rand() ,srand(),
#include<ctime> //time()
int main()
{
using namespace std;
using VECTOR::Vector;
srand(time(0)); //提供随机数种子
double directions;
Vector step;
Vector result(0.0, 0.0);
unsigned long steps = 0;
double target;
double dstep;
int times;
int counts = 1;
int MAX = 0;
int MIN = 999;
int total=0;
cout << "Enter how many times you wanna text: ";
cin >> times;
cout << "Enter target distance (q to quit): ";
while (counts<=times && cin >> target) //输入数字 -- true 输入字母 -- false
{
cout << "Enter step length: ";
if (!(cin >> dstep)) // 如果输入的不是数字,退出循环
{
break;
}
while (result.magval() < target) //矢量的长度小于目标长度
{
directions = rand() % 360; //通过随机值来设置下次走的方向
step.reset(dstep, directions, Vector::POL); //修改参数 -- 步子的长度,方向,以及表达方式
result = result + step; // 对象的重载相加
steps++; // 记录一共走了多少步
}
//cout << "After " << steps << " steps,the subject has the following location: " << endl;
//cout << result << endl; // 对象的cout显示在屏幕上 ( >>运算符的重载)
//result.polar_mode();
//cout << "or\n" << result << endl; // 重载 << 运算符的函数中的返回值为 ostream流的一个引用,所以可以连续使用<<运算符
//cout << "Average outward distance per step = " << result.magval() / steps << endl;
total += steps;
if (steps > MAX)
{
MAX = steps;
}
if (steps < MIN)
{
MIN = steps;
}
steps = 0; //要记录平均步数和最小最大步数等,steps值要保存 -- 所以在steps清零前要进行一系列的数据保存
result.reset(0.0, 0.0);
counts++;
cout << "Enter target distance(q to quit): ";
}
cout << "After the test: " << endl;
cout << "The maximum steps are: " << MAX << endl;
cout << "The minimum steps are: " << MIN << endl;
cout << "The average steps are: " << total / times << endl;
cout << "Bye~" << endl;
//若输入过程中输入了很多字符,则用下面这几行代码来清除,清除完成后即cin,get()!='\n',再结束程序
cin.clear();
while (cin.get() != '\n')
{
continue;
}
system("pause");
return 0;
}
//修改目标: 使程序报告N次测试中的最高,最低和平均步数(N为用户输入的整数),而不是报告每次测试的结果
//修改方法:创建一系列相关的变量,并在所需量steps被清零前进行数据记录即可
11.4
// class.h
#pragma once
#include<iostream>
#ifndef _CLASS_H_
#define _CLASS_H_
class Time
{
private:
int hours;
int minutes;
public:
Time();
Time(int h, int m = 0);
void AddMin(int m);
void AddHour(int h);
void Reset(int h = 0, int m = 0);
friend Time operator+(const Time& t1,const Time&t2);
friend Time operator-(const Time& t1,const Time&t2);
friend Time operator*(const Time&t,double n);
friend Time operator*(double m, const Time& t)
{
return t * m;
}
friend std::ostream& operator<<(std::ostream& os, const Time& t);
};
#endif
// fuc.cpp
#include"class.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::AddHour(int h)
{
hours += h;
}
void Time::Reset(int h, int m)
{
hours = h;
minutes = m;
}
Time operator+(const Time& t1,const Time&t2)
{
Time sum;
sum.minutes = t1.minutes + t2.minutes;
sum.hours = t1.hours + t2.hours + sum.minutes / 60;
sum.minutes %= 60;
return sum;
}
Time operator-(const Time& t1,const Time&t2)
{
Time diff;
int tot1, tot2;
tot1 = t2.minutes + 60 * t2.hours;
tot2 = t1.minutes + 60 * t1.hours;
diff.minutes = (tot2 - tot1) % 60;
diff.hours = (tot2 - tot1) / 60;
return diff;
}
Time operator*(const Time&t,double n)
{
Time result;
long totalminutes = t.hours * 60 * n + t.minutes * n; // n是用户自己输入的倍数
result.hours = totalminutes / 60;
result.minutes = totalminutes % 60;
return result;
}
std::ostream& operator<<(std::ostream& os, const Time& t)
{
os << t.hours << "hours, " << t.minutes << " minutes";
return os;
}
// main.cpp
//修改目标:使用友元函数来实现所有的重载运算符
#include"class.h"
using namespace std;
int main()
{
Time aida(3, 35);
Time tosca(2, 48);
Time temp;
cout << "Aida and Tosca:" << endl;
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;
}
//修改目标:使用友元函数来实现所有的重载运算符
//知识点:
1.友元函数不可以像成员函数那样在函数原型的后面加上const(只适用于成员函数)使private数据不被更改( eg: Time operator*(const Time&t) const),这种语法是不被允许的
2.友元函数重载的运算符一般有两个参数,而成员函数一般只有一个参数 (eg: 友元函数:friend Time operator+(const Time&t1,const Time&t2) ,成员函数: Time operator+(const Time&t) )
3.使用成员函数来重载运算符,调用时必须得运算符的左侧为对象,右侧为参数。而使用友元函数来重载运算符时,运算符的左右两侧均为参数,位置无关紧要。
4.成员函数重载调用本质: t1 + t2 -- t1.operator+(t2) -- 对象调用函数并传入一个参数
5.友元函数重载调用本质: t1 + t2 -- operator+(t1,t2) -- 调用函数并传入两个参数
11.5
//head.h
#pragma once
#include<iostream>
using namespace std;
#ifndef _CLASS_H_
#define _CLASS_H_
class Stonewt
{
private:
enum Mode{ Lbs_per_stn = 14,STN,LBS}; // static Lbs_per_stnd = 14
int stone;
double pds_left;
double pounds;
Mode mode; //控制格式
public:
Stonewt(double lbs,Mode m = STN); // 是接受一个参数的构造函数 -- 转换构造函数
Stonewt(int stn, double lbs,Mode me =STN);
Stonewt();
~Stonewt();
//重载运算符
friend ostream& operator<<(ostream& os, const Stonewt& t);
Stonewt operator+(const Stonewt&t)const;
Stonewt operator-(const Stonewt&t)const;
Stonewt operator*(double n)const;
// 转换函数
explicit operator int()const; // 必须要显示使用该转换函数 -- 加上了explicit
operator double()const;
};
#endif
// fuc.cpp
#include"class.h"
Stonewt::Stonewt(double lbs,Mode m)
{
mode = m;
stone = int(lbs) / Lbs_per_stn; // 强制类型转换: int (lbs) 和 (int) lbs 效果相同
pds_left = (int)lbs % Lbs_per_stn;
pounds = lbs;
}
Stonewt::Stonewt(int stn, double lbs,Mode m)
{
mode = m;
stone = stn;
pds_left = lbs;
pounds = stn * Lbs_per_stn + lbs;
}
Stonewt::Stonewt()
{
stone = pounds = pds_left = 0;
mode = STN;
}
Stonewt::~Stonewt()
{
}
// 重载运算符的实现
ostream& operator<<(ostream& os, const Stonewt& t)
{
if (t.mode == Stonewt::STN) //因为是友元函数,所以无法直接访问类中的枚举量,需要Stonewt::来间接访问
{
cout << t.pounds << " pounds" << endl;
}
else if (t.mode == Stonewt::LBS)
{
cout << t.stone << " stone, " << t.pds_left << " pounds" << endl;
}
return os;
}
Stonewt Stonewt::operator+(const Stonewt& t)const
{
Stonewt temp;
temp.pounds = pounds + t.pounds;
temp.stone = temp.pounds / temp.Lbs_per_stn;
temp.pds_left = (int)temp.pounds % temp.Lbs_per_stn; //浮点数无法进行取模运算,强制转换为整数型
return temp;
}
Stonewt Stonewt::operator-(const Stonewt& t)const
{
Stonewt temp;
temp.pounds = pounds - t.pounds;
temp.stone = temp.pounds / temp.Lbs_per_stn;
temp.pds_left = (int)temp.pounds % temp.Lbs_per_stn; //浮点数无法进行取模运算,强制转换为整数型
return temp;
}
Stonewt Stonewt::operator*(double n)const
{
Stonewt temp;
temp.pounds = pounds*n;
temp.stone = temp.pounds / temp.Lbs_per_stn;
temp.pds_left = (int)temp.pounds % temp.Lbs_per_stn; //浮点数无法进行取模运算,强制转换为整数型
return temp;
}
// 转换函数的定义
Stonewt::operator int()const
{
return int(pounds + 0.5); //实现返回整数型的四舍五入
}
Stonewt::operator double()const
{
return pounds;
}
// main.cpp
//1.转换构造函数:本质上就是只接受一个参数的构造函数
// 原理:构造函数在进行构造时会创建一个类对象副本来赋值,最后返回这个副本
// 使用:Stonewt inconito = 275 -- 利用了单参数构造函数来进行初始化 相当于 Stonewt inconito = Stonewt(275) 和 Stonewt inconito(275)
//2.转换函数: 语法: operator typename()
// 转换函数声明在类中,没有参数,也没有返回类型,但是在函数的定义中必须要有返回值,且这个返回值的类型与typename相同
//3. explicit可以可以关闭自动转换的特性,使得上述的两种转换函数必须要显示使用才可以发挥作用(explicit加在类的函数声明前即可)
//修改目标:
// 1.设置一个状态成员,控制对象的格式为英石格式,整数磅格式还是浮点磅格式 (利用enum枚举来实现)
// 2.重载 << 运算符,替换show_stn()和show_lbs()方法
// 3.重载+ - *运算符来对Stonewt值进行相应运算
//英石格式: 一英石等于14磅
#include"class.h"
int main()
{
Stonewt s1(10, 20);
Stonewt s2(5, 10);
cout << "s1: " << endl;
cout << s1 << endl;
cout << "s2: " << endl;
cout << s2 << endl;
Stonewt s3; //默认构造函数设置mode
s3 = s1 + s2;
cout << "s1+s2: " << endl;
cout << s3 << endl;
Stonewt s4; //默认构造函数设置mode
s4 = s1 - s2;
cout << "s1-s2: " << endl;
cout << s4 << endl;
Stonewt s5; //默认构造函数设置mode
s5 = s1*2.5;
cout << "s1*2.5: " << endl;
cout << s5 << endl;
system("pause");
return 0;
}
//修改目标:
// 1.设置一个状态成员,控制对象的格式为英石格式,整数磅格式还是浮点磅格式
// 2.重载 << 运算符,替换show_stn()和show_lbs()方法
// 3.重载+ - *运算符来对Stonewt值进行相应运算
//知识点:
1.浮点数不能进行求模运算,必须强制转换为整数
2.通过枚举enum来设置状态成员,来控制对象的格式 eg: enum Mode{STN,LBS}; Mode mode;
11.6
// class.h
#pragma once
#include<iostream>
using namespace std;
#ifndef _CLASS_H_
#define _CLASS_H_
class Stonewt
{
private:
enum { Lbs_per_stn = 14 }; // static Lbs_per_stnd = 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;
int restone()
{
return stone;
}
void refresh(int n)
{
stone = n;
}
// 转换函数 语法: operator typename() 无参数,无返回类型,声明在类中,但函数的定义中有与typename类型相同的返回值
explicit operator int()const; // 必须要显示使用该转换函数 -- 加上了explicit
operator double()const;
// 重载关系运算符
bool operator>(const Stonewt& t);
bool operator>=(const Stonewt& t);
bool operator<(const Stonewt& t);
bool operator<=(const Stonewt& t);
bool operator=(const Stonewt& t);
bool operator!=(const Stonewt& t);
};
#endif
// fuc.cpp
#include"class.h"
Stonewt::Stonewt(double lbs)
{
stone = int(lbs) / Lbs_per_stn; // 强制类型转换: int (lbs) 和 (int) lbs 效果相同
pds_left = (int)lbs % Lbs_per_stn;
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()
{
}
void Stonewt::show_stn()const
{
cout << stone << " stone, " << pds_left << " pounds" << std::endl;
}
void Stonewt::show_lbs()const
{
cout << pounds << " pounds" << std::endl;
}
// 转换函数的定义
Stonewt::operator int()const
{
return int(pounds + 0.5); //实现返回整数型的四舍五入
}
Stonewt::operator double()const
{
return pounds;
}
// 重载关系运算符的定义
bool Stonewt::operator>(const Stonewt& t)
{
if (stone > t.stone)
{
return true;
}
else
{
return false;
}
}
bool Stonewt::operator>=(const Stonewt& t)
{
if (stone >= t.stone)
{
return true;
}
else
{
return false;
}
}
bool Stonewt::operator<(const Stonewt& t)
{
if (stone < t.stone)
{
return true;
}
else
{
return false;
}
}
bool Stonewt::operator<=(const Stonewt& t)
{
if (stone <= t.stone)
{
return true;
}
else
{
return false;
}
}
bool Stonewt::operator=(const Stonewt& t)
{
if (stone = t.stone)
{
return true;
}
else
{
return false;
}
}
bool Stonewt::operator!=(const Stonewt& t)
{
if (stone != t.stone)
{
return true;
}
else
{
return false;
}
}
// main.cpp
//1.转换构造函数:本质上就是只接受一个参数的构造函数
// 原理:构造函数在进行构造时会创建一个类对象副本来赋值,最后返回这个副本
// 使用:Stonewt inconito = 275 -- 利用了单参数构造函数来进行初始化 相当于 Stonewt inconito = Stonewt(275) 和 Stonewt inconito(275)
//2.转换函数: 语法: operator typename()
// 转换函数声明在类中,没有参数,也没有返回类型,但是在函数的定义中必须要有返回值,且这个返回值的类型与typename相同
//3. explicit可以可以关闭自动转换的特性,使得上述的两种转换函数必须要显示使用才可以发挥作用(explicit加在类的函数声明前即可)
//修改目标:
// 1.重载六个关系运算符: > >= < <= == != 并返回bool值
// 2.程序中声明一个包含六个对象的数组,并在数组声明中初始化前三个对象,然后使用循环来设置剩余的三个对象。
// 3.报告数组中最小的元素,最大的元素(stone英石的大小),以及大于或等于11英石的数量
#include"class.h"
int main()
{
Stonewt s[6] =
{
{100},
{80},
{120},
};
int t;
for (int i = 3; i < 6; i++)
{
cout << "为第" << i + 1 << "个对象初始化" << endl;
cin >> t;
s[i] = t; //利用了只有一个参数的构造函数 -- 即转换构造函数(可以将值赋给对象,相当于调用构造函数)
}
Stonewt temp = Stonewt(154);
int counts = 0;
Stonewt MAX = Stonewt(0);
Stonewt MIN = Stonewt(9999);
int Max;
int Min;
for (int i = 0; i < 6; i++)
{
if (s[i] > MAX)
{
Max = s[i].restone(); //储存目前来说的最大值
MAX.refresh(Max); //更新MAX中的stone值
}
if (s[i] < MIN)
{
Min = s[i].restone(); //储存目前来说的最小值
MIN.refresh(Min); //更新MIN中的stone值
}
if (s[i] > temp)
{
counts++;
}
}
cout << "The maximum stone in the array: " << Max << endl;
cout << "The minimum stone in the array: " << Min << endl;
cout << "The numbers that above 11 stones: " << counts << endl;
system("pause");
return 0;
}
//修改目标:
// 1.重载六个关系运算符: > >= < <= == != 并返回bool值
// 2.程序中声明一个包含六个对象的数组,并在数组声明中初始化前三个对象,然后使用循环来设置剩余的三个对象。
// 3.报告数组中最小的元素,最大的元素(stone英石的大小),以及大于或等于11英石的数量
//知识点:
1.为了储存对象中private数据的最值,创建了restone函数和refresh函数,restone函数用于返回对象中的stone值,refresh函数用于更新MAX和MIN对象中的stone值以进行接下来的比较。
2.给对象数组赋值可以利用单参数构造函数,也就是转换构造函数,S[i] = 值 来进行对象数组元素的初始化。
3.转换构造函数 -- 即单参数构造函数
4.转换函数 -- operator typename() 无参数,无返回类型,声明在类中,但函数的定义中需要返回此typename类型的值
11.7
// class.h
#pragma once
#include<iostream>
using namespace std;
#ifndef _CLASS_H_
#define _CLASS_H_
class Complex
{
private:
double RE;
double IM;
public:
Complex();
Complex(double r, double i);
~Complex();
//重载运算符
Complex operator+(const Complex& t)const;
Complex operator-(const Complex& t)const;
Complex operator*(const Complex& t)const;
Complex operator*(double n); //直接修改调用对象的值,不能加const
Complex operator~(); //直接修改调用对象的值,不能加const
friend istream& operator>>(istream& is, Complex& t); //要修改对象的值,不能给对象参数加上const // 输入流 istream << 和 输出流 ostream >>对应
friend ostream& operator<<(ostream& os, const Complex& t);
};
#endif
// fuc.cpp
#include"class.h"
Complex::Complex()
{
RE = IM = 0;
}
Complex::Complex(double r, double i)
{
RE = r;
IM = i;
}
Complex::~Complex()
{
}
//重载运算符
Complex Complex::operator+(const Complex& t)const
{
Complex temp;
temp.RE = RE + t.RE;
temp.IM = IM + t.IM;
return temp; //也可以直接用构造函数 return Complex(RE+t.RE,IM+t.IM)
}
Complex Complex::operator-(const Complex& t)const
{
Complex temp;
temp.RE = RE - t.RE;
temp.IM = IM - t.IM;
return temp;
}
Complex Complex::operator*(const Complex& t)const
{
Complex temp;
temp.RE = RE * t.RE - IM * t.IM;
temp.IM = RE * t.IM + t.RE * IM;
return temp;
}
Complex Complex::operator*(double n)//直接修改调用对象的值,不能加const
{
return Complex(2 * RE, 2 * IM); //利用构造函数
}
Complex Complex::operator~() //直接修改调用对象的值,不能加const
{
return Complex(RE, -IM);
}
//友元函数重载运算符 -- 无需加friend(只需在类声明中加上) 无需在函数名前加上 Complex::
istream& operator>>(istream& is, Complex& t) // 输入流 istream >> 和 输出流 ostream <<对应
{
cout << "Real: " << endl;
is >> t.RE;
cout << "Imaginary: " << endl;
is >> t.IM;
return is;
}
ostream& operator<<(ostream& os, const Complex& t)
{
os << "( " << t.RE << " , " << t.IM << "i )" << endl;
return os;
}
// main.cpp
//程序任务: 设置一个类来完成复数的相关运算,输入,输出
// 1.重载加法,减法,乘法(与复数和与常数),共轭
// 2.重载<< 和 >> ,同时使得cin>>x 要输入实数和虚数两个值
#include"class.h"
int main()
{
Complex a(3.0, 4.0);
Complex c;
cout << "Enter a complex number (q to quit)" << endl;
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 " << c * 2 << endl;
cout << "Enter a complex number(q to quit)" << endl;
}
cout << "Done!" << endl;
system("pause");
return 0;
}
//程序任务: 设置一个类来完成复数的相关运算,输入,输出
// 1.重载加法,减法,乘法(与复数和与常数),共轭
// 2.重载<< 和 >> ,同时使得cin>>x 要输入实数和虚数两个值
//知识点:
1.输入流 istream >> 和 输出流 ostream <<对应
ostream& operator >>(ostream&os,const Complex &t) 输出流重载
istream& operator <<(istream&is, Complex &t) 输入流重载
2.重载运算符时可以利用构造函数
Complex temp;
temp.RE = RE + t.RE;
temp.IM = IM + t.IM;
return temp;
上述代码相当于直接用构造函数 return Complex(RE+t.RE,IM+t.IM)