习题选自:C Primer Plus(第六版) 内容仅供参考,如有错误,欢迎指正 ! 原文首发公众号iDoitnow
一般来说,访问私有成员的唯一方法是使用类方法,c 使用友元函数来避开这种限制,要让函数成为友元,需在类声明中声明该函数,并在声明前加上关键字friend。 运算符函数可以是类成员函数,也可以是友元函数(有一些运算符函数只能是类成员函数),如果要使其第一个操作数不是类对象,则必须使用友元函数,这样就可以将操作数按所需的顺序传递给函数了。
复习题
1.使用成员函数Stonewt类重载乘法运算符,该运算符将数据成员与double类型的值相乘。注意使用英石和磅表示时,需要进位。也就是说,将10英石8磅乘以2等于21英石2磅(1 英石=14 磅)。
代码语言:c 复制Stonewt Stonewt::operator*(double a)
{
this->stone=this->stone*a this->pounds*a/14;
this->pounds=(this->pounds*a);
return *this;
}
2.友元函数和成员函数之间的区别是什么?
成员函数是类定义的一部分,通过特定的对象来调用。成员函数可以隐式访问调用对象的成员,而无需使用成员运算符。友元函数不是类的组成部分,因此被称为直接函数调用。友元函数不能隐式访问类成员,而需要将成员运算符用作参数传递的对象。
3.非成员函数必须是友元才能访问类成员吗?
要访问私有成员,它必须是友元,但要访问共有成员,可以不是友元。
4.使用友元函数为Stonewt类重载乘法运算符,该运算符将double值与Stone值相乘。
代码语言:c 复制friend Stonewt Stonewt::operator*(double a, Stonewt &s);
Stonewt operator*(double a, Stonewt &s)
{
s.stone = s.stone * a s.pounds * a / 14;
s.pounds=( s.pounds * a ) % 14;
return s;
}
5.那些运算符不能重载?
- sizeof
- .
- .*
- ::
- ?:
6.在重载运算符=、( )、 和->时,有什么限制?
这些运算符必须使用成员函数来定义。
7.为Vector类定义一个转换函数,将Vector类转换为一个double类型的值,后者表示矢量的长度。
代码语言:c 复制operator double() {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
vect.h:
代码语言:c 复制// vect.h -- Vector class with <<, mode state
#ifndef VECTOR_H_
#define VECTOR_H_
#include <iostream>
namespace VECTOR
{
class Vector
{
public:
enum Mode {RECT, POL};
// RECT for rectangular, POL for Polar modes
private:
double x; // horizontal value
double y; // vertical value
double mag; // length of vector
double ang; // direction of vector in degrees
Mode mode; // RECT or POL
// private methods for setting values
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;} // report x value
double yval() const {return y;} // report y value
double magval() const {return mag;} // report magnitude
double angval() const {return ang;} // report angle
void polar_mode(); // set mode to POL
void rect_mode(); // set mode to RECT
// operator overloading
Vector operator (const Vector & b) const;
Vector operator-(const Vector & b) const;
Vector operator-() const;
Vector operator*(double n) const;
// friends
friend Vector operator*(double n, const Vector & a);
friend std::ostream & operator<<(std::ostream & os, const Vector & v);
};
} // end namespace VECTOR
#endif
vect.cpp:
代码语言:c 复制// vect.cpp -- methods for the Vector class
#include <cmath>
#include "vect.h" // includes <iostream>
using std::sqrt;
using std::sin;
using std::cos;
using std::atan;
using std::atan2;
using std::cout;
namespace VECTOR
{
// compute degrees in one radian
const double Rad_to_deg = 45.0 / atan(1.0);
// should be about 57.2957795130823
// private methods
// calculates magnitude from x and y
void Vector::set_mag()
{
mag = sqrt(x * x y * y);
}
void Vector::set_ang()
{
if (x == 0.0 && y == 0.0)
ang = 0.0;
else
ang = atan2(y, x);
}
// set x from polar coordinate
void Vector::set_x()
{
x = mag * cos(ang);
}
// set y from polar coordinate
void Vector::set_y()
{
y = mag * sin(ang);
}
// public methods
Vector::Vector() // default constructor
{
x = y = mag = ang = 0.0;
mode = RECT;
}
// construct vector from rectangular coordinates if form is r
// (the default) or else from polar coordinates if form is p
Vector::Vector(double n1, double n2, Mode form)
{
mode = form;
if (form == RECT)
{
x = n1;
y = n2;
set_mag();
set_ang();
}
else if (form == POL)
{
mag = n1;
ang = n2 / Rad_to_deg;
set_x();
set_y();
}
else
{
cout << "Incorrect 3rd argument to Vector() -- ";
cout << "vector set to 0n";
x = y = mag = ang = 0.0;
mode = RECT;
}
}
// reset vector from rectangular coordinates if form is
// RECT (the default) or else from polar coordinates if
// form is POL
void Vector:: reset(double n1, double n2, Mode form)
{
mode = form;
if (form == RECT)
{
x = n1;
y = n2;
set_mag();
set_ang();
}
else if (form == POL)
{
mag = n1;
ang = n2 / Rad_to_deg;
set_x();
set_y();
}
else
{
cout << "Incorrect 3rd argument to Vector() -- ";
cout << "vector set to 0n";
x = y = mag = ang = 0.0;
mode = RECT;
}
}
Vector::~Vector() // destructor
{
}
void Vector::polar_mode() // set to polar mode
{
mode = POL;
}
void Vector::rect_mode() // set to rectangular mode
{
mode = RECT;
}
// operator overloading
// add two Vectors
Vector Vector::operator (const Vector & b) const
{
return Vector(x b.x, y b.y);
}
// subtract Vector b from a
Vector Vector::operator-(const Vector & b) const
{
return Vector(x - b.x, y - b.y);
}
// reverse sign of Vector
Vector Vector::operator-() const
{
return Vector(-x, -y);
}
// multiply vector by n
Vector Vector::operator*(double n) const
{
return Vector(n * x, n * y);
}
// friend methods
// multiply n by Vector a
Vector operator*(double n, const Vector & a)
{
return a * n;
}
// display rectangular coordinates if mode is RECT,
// else display polar coordinates if mode is POL
std::ostream & operator<<(std::ostream & os, const Vector & v)
{
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;
}
} // end namespace VECTOR
randwalk.cpp:
代码语言:c 复制// randwalk.cpp -- using the Vector class
// compile with the vect.cpp file
#include <iostream>
#include <cstdlib> // rand(), srand() prototypes
#include <ctime> // time() prototype
#include "vect.h"
#include <fstream>
int main()
{
using namespace std;
using VECTOR::Vector;
srand(time(0)); // seed random-number generator
double direction;
Vector step;
Vector result(0.0, 0.0);
unsigned long steps = 0;
double target;
double dstep;
//for write
ofstream fout;
fout.open("walkinfo.txt");
cout << "Enter target distance (q to quit): ";
while (cin >> target)
{
cout << "Enter step length: ";
if (!(cin >> dstep))
break;
//write to file
fout << "Target Destance: " << target << ", ";
fout << "Step Size: " << dstep << endl;
while (result.magval() < target)
{
direction = rand() % 360;
step.reset(dstep, direction, Vector::POL);
result = result step;
fout << steps << ": " << result << endl;
steps ;
}
cout << "After " << steps << " steps, the subject "
"has the following location:n";
cout << result << endl;
result.polar_mode();
cout << " orn" << result << endl;
cout << "Average outward distance per step = "
<< result.magval()/steps << endl;
fout << "After " << steps << " steps, the subject "
"has the following location:n";
fout << result << endl;
result.polar_mode();
fout << " orn" << result << 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!n";
/* keep window open
cin.clear();
while (cin.get() != 'n')
continue;
cin.get();
*/
fout.close();
return 0;
}
2.对vector类的头文件(程序清单11.13)和实现文件(程序清单11.14)进行修改,使其不再存储矢量的长度和角度,而是在magval()和angval()被调用时计算他们。应保留公有接口不变(公有方法及其参数不变),但对私有部分(包括一些私有方法)和方法实现进行修改。然后,使用程序清单11.15对修改后的版本进行测试,结果应该与以前相同,因为vector类的公有接口与原来相同。
vect.h:
代码语言:c 复制// vect.h -- Vector class with <<, mode state
#ifndef VECTOR_H_
#define VECTOR_H_
#include <iostream>
namespace VECTOR
{
class Vector
{
public:
enum Mode {RECT, POL};
// RECT for rectangular, POL for Polar modes
private:
double x; // horizontal value
double y; // vertical value
Mode mode; // RECT or POL
// private methods for setting values
double get_mag() const;
double get_ang() const;
double get_x();
double get_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;} // report x value
double yval() const {return y;} // report y value
double magval() const {return get_mag();} // report magnitude
double angval() const {return get_ang();} // report angle
void polar_mode(); // set mode to POL
void rect_mode(); // set mode to RECT
// operator overloading
Vector operator (const Vector & b) const;
Vector operator-(const Vector & b) const;
Vector operator-() const;
Vector operator*(double n) const;
// friends
friend Vector operator*(double n, const Vector & a);
friend std::ostream & operator<<(std::ostream & os, const Vector & v);
};
} // end namespace VECTOR
#endif
vect.cpp:
代码语言:c 复制// vect.cpp -- methods for the Vector class
#include <cmath>
#include "vect.h" // includes <iostream>
using std::sqrt;
using std::sin;
using std::cos;
using std::atan;
using std::atan2;
using std::cout;
namespace VECTOR
{
// compute degrees in one radian
const double Rad_to_deg = 45.0 / atan(1.0);
// should be about 57.2957795130823
// private methods
// calculates magnitude from x and y
double Vector::get_mag() const
{
return sqrt(x * x y * y);
}
double Vector::get_ang() const
{
if (x == 0.0 && y == 0.0)
return 0.0;
else
return atan2(y, x);
}
// set x from polar coordinate
double Vector::get_x()
{
return get_mag() * cos(get_ang());
}
// set y from polar coordinate
double Vector::get_y()
{
return get_mag() * sin(get_ang());
}
// public methods
Vector::Vector() // default constructor
{
x = y = 0.0;
mode = RECT;
}
// construct vector from rectangular coordinates if form is r
// (the default) or else from polar coordinates if form is p
Vector::Vector(double n1, double n2, Mode form)
{
mode = form;
if (form == RECT)
{
x = n1;
y = n2;
}
else if (form == POL)
{
x =n1 * cos(n2);
y =n1 * sin(n2);
}
else
{
cout << "Incorrect 3rd argument to Vector() -- ";
cout << "vector set to 0n";
x = y = 0.0;
mode = RECT;
}
}
// reset vector from rectangular coordinates if form is
// RECT (the default) or else from polar coordinates if
// form is POL
void Vector:: reset(double n1, double n2, Mode form)
{
mode = form;
if (form == RECT)
{
x = n1;
y = n2;
}
else if (form == POL)
{
x =n1 * cos(n2);
y =n1 * sin(n2);
}
else
{
cout << "Incorrect 3rd argument to Vector() -- ";
cout << "vector set to 0n";
x = y = 0.0;
mode = RECT;
}
}
Vector::~Vector() // destructor
{
}
void Vector::polar_mode() // set to polar mode
{
mode = POL;
}
void Vector::rect_mode() // set to rectangular mode
{
mode = RECT;
}
// operator overloading
// add two Vectors
Vector Vector::operator (const Vector & b) const
{
return Vector(x b.x, y b.y);
}
// subtract Vector b from a
Vector Vector::operator-(const Vector & b) const
{
return Vector(x - b.x, y - b.y);
}
// reverse sign of Vector
Vector Vector::operator-() const
{
return Vector(-x, -y);
}
// multiply vector by n
Vector Vector::operator*(double n) const
{
return Vector(n * x, n * y);
}
// friend methods
// multiply n by Vector a
Vector operator*(double n, const Vector & a)
{
return a * n;
}
// display rectangular coordinates if mode is RECT,
// else display polar coordinates if mode is POL
std::ostream & operator<<(std::ostream & os, const Vector & v)
{
if (v.mode == Vector::RECT)
os << "(x,y) = (" << v.x << ", " << v.y << ")";
else if (v.mode == Vector::POL)
{
os << "(m,a) = (" << v.magval() << ", "
<< v.angval() * Rad_to_deg << ")";
}
else
os << "Vector object mode is invalid";
return os;
}
} // end namespace VECTOR
randwalk.cpp:
代码语言:C 复制// randwalk.cpp -- using the Vector class
// compile with the vect.cpp file
#include <iostream>
#include <cstdlib> // rand(), srand() prototypes
#include <ctime> // time() prototype
#include "vect.h"
int main()
{
using namespace std;
using VECTOR::Vector;
srand(time(0)); // seed random-number generator
double direction;
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)
{
cout << "Enter step length: ";
if (!(cin >> dstep))
break;
while (result.magval() < target)
{
direction = rand() % 360;
step.reset(dstep, direction, Vector::POL);
result = result step;
steps ;
}
cout << "After " << steps << " steps, the subject "
"has the following location:n";
cout << result << endl;
result.polar_mode();
cout << " orn" << result << endl;
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!n";
/* keep window open
cin.clear();
while (cin.get() != 'n')
continue;
cin.get();
*/
return 0;
}
3.修改程序清单11.15,使之报告N次测试中的提高、最低和平均步数(其中N是用户输入的整数),而不是报告每次测试的结果。
vect.h:
代码语言:c 复制// vect.h -- Vector class with <<, mode state
#ifndef VECTOR_H_
#define VECTOR_H_
#include <iostream>
namespace VECTOR
{
class Vector
{
public:
enum Mode {RECT, POL};
// RECT for rectangular, POL for Polar modes
private:
double x; // horizontal value
double y; // vertical value
double mag; // length of vector
double ang; // direction of vector in degrees
Mode mode; // RECT or POL
// private methods for setting values
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;} // report x value
double yval() const {return y;} // report y value
double magval() const {return mag;} // report magnitude
double angval() const {return ang;} // report angle
void polar_mode(); // set mode to POL
void rect_mode(); // set mode to RECT
// operator overloading
Vector operator (const Vector & b) const;
Vector operator-(const Vector & b) const;
Vector operator-() const;
Vector operator*(double n) const;
// friends
friend Vector operator*(double n, const Vector & a);
friend std::ostream & operator<<(std::ostream & os, const Vector & v);
};
} // end namespace VECTOR
#endif
vect.cpp:
代码语言:c 复制// vect.cpp -- methods for the Vector class
#include <cmath>
#include "vect.h" // includes <iostream>
using std::sqrt;
using std::sin;
using std::cos;
using std::atan;
using std::atan2;
using std::cout;
namespace VECTOR
{
// compute degrees in one radian
const double Rad_to_deg = 45.0 / atan(1.0);
// should be about 57.2957795130823
// private methods
// calculates magnitude from x and y
void Vector::set_mag()
{
mag = sqrt(x * x y * y);
}
void Vector::set_ang()
{
if (x == 0.0 && y == 0.0)
ang = 0.0;
else
ang = atan2(y, x);
}
// set x from polar coordinate
void Vector::set_x()
{
x = mag * cos(ang);
}
// set y from polar coordinate
void Vector::set_y()
{
y = mag * sin(ang);
}
// public methods
Vector::Vector() // default constructor
{
x = y = mag = ang = 0.0;
mode = RECT;
}
// construct vector from rectangular coordinates if form is r
// (the default) or else from polar coordinates if form is p
Vector::Vector(double n1, double n2, Mode form)
{
mode = form;
if (form == RECT)
{
x = n1;
y = n2;
set_mag();
set_ang();
}
else if (form == POL)
{
mag = n1;
ang = n2 / Rad_to_deg;
set_x();
set_y();
}
else
{
cout << "Incorrect 3rd argument to Vector() -- ";
cout << "vector set to 0n";
x = y = mag = ang = 0.0;
mode = RECT;
}
}
// reset vector from rectangular coordinates if form is
// RECT (the default) or else from polar coordinates if
// form is POL
void Vector:: reset(double n1, double n2, Mode form)
{
mode = form;
if (form == RECT)
{
x = n1;
y = n2;
set_mag();
set_ang();
}
else if (form == POL)
{
mag = n1;
ang = n2 / Rad_to_deg;
set_x();
set_y();
}
else
{
cout << "Incorrect 3rd argument to Vector() -- ";
cout << "vector set to 0n";
x = y = mag = ang = 0.0;
mode = RECT;
}
}
Vector::~Vector() // destructor
{
}
void Vector::polar_mode() // set to polar mode
{
mode = POL;
}
void Vector::rect_mode() // set to rectangular mode
{
mode = RECT;
}
// operator overloading
// add two Vectors
Vector Vector::operator (const Vector & b) const
{
return Vector(x b.x, y b.y);
}
// subtract Vector b from a
Vector Vector::operator-(const Vector & b) const
{
return Vector(x - b.x, y - b.y);
}
// reverse sign of Vector
Vector Vector::operator-() const
{
return Vector(-x, -y);
}
// multiply vector by n
Vector Vector::operator*(double n) const
{
return Vector(n * x, n * y);
}
// friend methods
// multiply n by Vector a
Vector operator*(double n, const Vector & a)
{
return a * n;
}
// display rectangular coordinates if mode is RECT,
// else display polar coordinates if mode is POL
std::ostream & operator<<(std::ostream & os, const Vector & v)
{
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;
}
} // end namespace VECTOR
randwalk.cpp:
代码语言:c 复制// randwalk.cpp -- using the Vector class
// compile with the vect.cpp file
#include <iostream>
#include <cstdlib> // rand(), srand() prototypes
#include <ctime> // time() prototype
#include "vect.h"
int main()
{
using namespace std;
using VECTOR::Vector;
srand(time(0)); // seed random-number generator
double direction;
Vector step;
Vector result(0.0, 0.0);
unsigned long steps = 0;
double target;
double dstep;
int times;
unsigned long max, min;
max = min = 0;
cout << "Enter Times:";
if(!(cin >> times))
{
cout << "Input error !, program ended." << endl;
return 0;
}
cout << "Enter target distance (q to quit): ";
for(int i = 0; i < times; i)
{
cin >> target;
cout << "Enter step length: ";
if(!(cin >> dstep))
{
break;
}
while(result.magval() < target)
{
direction = rand() % 360;
step.reset(dstep, direction, Vector::POL);
result = result step;
steps ;
}
if(min == 0)
{
min = steps;
}
if(steps > max)
{
max = steps;
}
else if(steps < min)
{
min = steps;
}
result.reset(0.0, 0.0);
if(i < times - 1)
{
cout << "Enter target distance (q to quit): ";
}
}
cout << "Max: " << max << endl;
cout << "Min: " << min << endl;
cout << "Bye!n";
/* keep window open
cin.clear();
while (cin.get() != 'n')
continue;
cin.get();
*/
return 0;
}
4.重新编写最后的Time类示例(程序清单11.10、程序清单11.11和程序清单11.12),使用友元函数来实现所有的重载运算符。
mytime3.h:
代码语言:c 复制// mytime3.h -- Time class with friends
#ifndef MYTIME3_H_
#define MYTIME3_H_
#include <iostream>
class Time
{
private:
int hours;
int minutes;
public:
Time();
Time(int h, int m = 0);
void AddMin(int m);
void AddHr(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 m);
friend Time operator*(double m, const Time & t)
{ return t * m; } // inline definition
friend std::ostream & operator<<(std::ostream & os, const Time & t);
};
#endif
mytime3.cpp:
代码语言:c 复制// mytime3.cpp -- implementing Time methods
#include "mytime3.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;
}
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 = t1.minutes 60 * t1.hours;
tot2 = t2.minutes 60 * t2.hours;
diff.minutes = (tot2 - tot1) % 60;
diff.hours = (tot2 - tot1) / 60;
return diff;
}
Time operator*(const Time & t, double m)
{
Time result;
long totalminutes = t.hours * m * 60 t.minutes * m;
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;
}
usetime3.cpp:
代码语言:c 复制//usetime3.cpp -- using the fourth draft of the Time class
// compile usetime3.cpp and mytime3.cpp together
#include <iostream>
#include "mytime3.h"
int main()
{
using std::cout;
using std::endl;
Time aida(3, 35);
Time tosca(2, 48);
Time temp;
cout << "Aida and Tosca:n";
cout << aida<<"; " << tosca << endl;
temp = aida tosca; // operator ()
cout << "Aida Tosca: " << temp << endl;
temp = aida* 1.17; // member operator*()
cout << "Aida * 1.17: " << temp << endl;
cout << "10.0 * Tosca: " << 10.0 * tosca << endl;
// std::cin.get();
return 0;
}
5.重新编写Stonewt类(程序清单11.16和程序清单11.17),使他有一个状态成员,由该成员控制对象转换为英石格式、整数磅格式还是浮点磅格式。重载<<
运算符,使用它来替换show_stn()
和show_lbs()
方法。重载加法、减法和乘法运算符,以便可以对Stonewt值进行加、减、乘运算。编写一个使用所有类方法和友元的小程序,来测试这个类。
stonewt.h:
代码语言:c 复制// stonewt.h -- definition for the Stonewt class
#ifndef STONEWT_H_
#define STONEWT_H_
#include<iostream>
class Stonewt
{
public:
enum Mode{STN, PDS};
private:
enum {Lbs_per_stn = 14}; // pounds per stone
int stone; // whole stones
double pds_left; // fractional pounds
double pounds; // entire weight in pounds
Mode mode;
public:
Stonewt(double lbs, Mode m = STN); // constructor for double pounds
Stonewt(int stn, double lbs, Mode m = STN); // constructor for stone, lbs
Stonewt(); // default constructor
~Stonewt();
void set_mode(Mode m){ mode = m;}
Stonewt operator (const Stonewt & st) const;
Stonewt operator-(const Stonewt & st) const;
Stonewt operator*(double n) const;
friend Stonewt operator*(double n, const Stonewt & st)
{
return st * n;
}
friend std::ostream & operator<<(std::ostream & os, const Stonewt & st);
};
#endif
stonewt.cpp:
代码语言:c 复制// stonewt.cpp -- Stonewt methods
#include <iostream>
using std::cout;
#include "stonewt.h"
// construct Stonewt object from double value
Stonewt::Stonewt(double lbs, Mode m)
{
stone = int (lbs) / Lbs_per_stn; // integer division
pds_left = int (lbs) % Lbs_per_stn lbs - int(lbs);
pounds = lbs;
mode = m;
}
// construct Stonewt object from stone, double values
Stonewt::Stonewt(int stn, double lbs, Mode m)
{
stone = stn;
pds_left = lbs;
pounds = stn * Lbs_per_stn lbs;
mode = m;
}
Stonewt::Stonewt() // default constructor, wt = 0
{
stone = pounds = pds_left = 0;
mode = STN;
}
Stonewt::~Stonewt() // destructor
{
}
Stonewt Stonewt::operator (const Stonewt & st) const
{
double sum = pounds st.pounds;
return Stonewt(sum);
}
Stonewt Stonewt::operator-(const Stonewt & st) const
{
double diff = pounds - st.pounds;
return Stonewt(diff);
}
Stonewt Stonewt::operator*(double n) const
{
double multi = pounds * n;
return Stonewt(multi);
}
std::ostream & operator<<(std::ostream & os, const Stonewt & st)
{
if(st.mode == Stonewt::STN)
{
std::cout << st.stone << " stone, " << st.pds_left << "pounds";
}
else if(st.mode == Stonewt::PDS)
{
std::cout << st.pounds << "pounds";
}
else
{
std::cout << "Mode error!" << std::endl;
}
}
main.cpp:
代码语言:c 复制#include "stonewt.h"
#include <iostream>
int main()
{
using std::cout;
using std::endl;
Stonewt s1;
Stonewt s2 = Stonewt(1, 2);
Stonewt s3 = Stonewt(20.65, Stonewt::PDS);
cout << "s1(STN): " << s1 << endl;
cout << "s2(STN): " << s2 << endl;
cout << "s3(PDS): " << s3 << endl;
s3.set_mode(Stonewt::STN);
cout << "s3(STN): " << s3 << endl;
cout << "s3 - s2 = " << s3 - s2 << endl;
cout << "s3 s2 = " << s3 s2 << endl;
cout << "2*s2 = " << 2 * s2 << endl;
cout << "s2*2 = " << s2 * 2 << endl;
return 0;
}
6.重新编写Stonewt类(程序清单11.16和程序清单11.17),重载全部6个关系云算符。运算符对pounds成员进行比较,并返回一个bool值。编写一个程序,它声明一个包含6个Stonewt对象的数组,并在数组声明中初始化前3个对象。然后使用循环来读取用于设置剩余3个数组元素的值。接着报告最小的元素、最大的元素以及大于或等于11英石的元素数量(最简单的方法是创建一个Stonewt对象,并将其初始化为11英石,然后将其同其他对象进行比较)。
stonewt.h:
代码语言:c 复制// stonewt.h -- definition for the Stonewt class
#ifndef STONEWT_H_
#define STONEWT_H_
class Stonewt
{
private:
enum {Lbs_per_stn = 14}; // pounds per stone
int stone; // whole stones
double pds_left; // fractional pounds
double pounds; // entire weight in pounds
public:
Stonewt(double lbs); // constructor for double pounds
Stonewt(int stn, double lbs); // constructor for stone, lbs
Stonewt(); // default constructor
~Stonewt();
void show_stn() const;
void show_lbs() const;
bool operator==(const Stonewt& st)const;
bool operator!=(const Stonewt& st)const;
bool operator>(const Stonewt& st)const;
bool operator<(const Stonewt& st)const;
bool operator>=(const Stonewt& st)const;
bool operator<=(const Stonewt& st)const;
};
#endif
stonewt.cpp:
代码语言:c 复制// stonewt.cpp -- Stonewt methods
#include <iostream>
using std::cout;
#include "stonewt.h"
// construct Stonewt object from double value
Stonewt::Stonewt(double lbs)
{
stone = int (lbs) / Lbs_per_stn; // integer division
pds_left = int (lbs) % Lbs_per_stn lbs - int(lbs);
pounds = lbs;
}
// construct Stonewt object from stone, double values
Stonewt::Stonewt(int stn, double lbs)
{
stone = stn;
pds_left = lbs;
pounds = stn * Lbs_per_stn lbs;
}
Stonewt::Stonewt() // default constructor, wt = 0
{
stone = pounds = pds_left = 0;
}
Stonewt::~Stonewt() // destructor
{
}
// show weight in stones
void Stonewt::show_stn() const
{
cout << stone << " stone, " << pds_left << " poundsn";
}
// show weight in pounds
void Stonewt::show_lbs() const
{
cout << pounds << " poundsn";
}
bool Stonewt::operator==(const Stonewt& st)const
{
return pounds == st.pounds;
}
bool Stonewt::operator!=(const Stonewt& st)const
{
return pounds != st.pounds;
}
bool Stonewt::operator>(const Stonewt& st)const
{
return pounds > st.pounds;
}
bool Stonewt::operator<(const Stonewt& st)const
{
return pounds < st.pounds;
}
bool Stonewt::operator>=(const Stonewt& st)const
{
return pounds >= st.pounds;
}
bool Stonewt::operator<=(const Stonewt& st)const
{
return pounds <= st.pounds;
}
main.cpp:
代码语言:c 复制#include "stonewt.h"
#include <iostream>
int main()
{
using std::cout;
using std::endl;
using std::cin;
Stonewt arr[6] = {30, 12, 26};
for(int i = 3; i < 6; i )
{
cout << "Stonewt[" << i << "]: ";
double st;
cin >> st;
arr[i] = Stonewt(st);
}
Stonewt max = arr[0], min = arr[0];
int num = 0;
Stonewt eleven = Stonewt(11, 0.0);
for(int i = 0; i < 6; i)
{
if(arr[i] > max)
max = arr[i];
if(arr[i] < min)
min = arr[i];
if(arr[i] > eleven)
num ;
}
cout << "max: " << endl;
max.show_lbs();
cout << "min: " << endl;
min.show_lbs();
cout << num << " elements > 11 stones" << endl;
return 0;
}
7.复数有两个部分组成:实数部分和虚数部分。复数的一种写法方式是:(3.0, 4.0),其中,3.0是实数部分,4.0是虚数部分。假设a=(A,Bi),c=(C,Di),则下面是一些复数运算。
- 加法:a c=(A C,(B D)i)。
- 减法:a-c=(A-C,(B-D)i)。
- 乘法:a*c=(A*C-B*D, (A*D B*C)i)。
- 乘法:x*c=(x*C,x*Di)。
- 共轭:a=(A,-Bi)。
请定义一个复数类,以便下面的程序可以使用它来获得正确的结果。
#include<iostream> using namespace std; #include "complex0.h" 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 <<'n'; cout << "complex conjugate is " << ~c <<'n'; cout << "a is " << a << 'n'; cout << "a c is " << a c << 'n'; cout << "a - c is " << a - c << 'n'; cout << "a * c is " << a * c << 'n'; cout << "2 * c is " << 2 * c << 'n'; cout << "Enter a complex number (q to quit):n"; } cout << "Done! n"; return 0; }
注意,必须重载运算符<<和>>。标准c 使用头文件complex提供了比这个示例更广泛的复数支持,因此应将自己定义的头文件命名为complex0.h,以免发生冲突。应尽可能使用const。
下面是该程序的运行情况。
Enbter a complex number (q to quit): real:10 imaginary:12 c is (10,12i) complex conjugate is (10, -12i) a is (3,4i) a c is (13,16i) a - c is (-7,78i) a * c is (-18,76i) 2 c is (20,24i) Enbter a complex number (q to quit): real:q Done!
请注意,经过重载后,cin>>c 将提示用户输入实数和虚数部分。
complex0.h:
代码语言:c 复制#ifndef COMPLEX0_H
#define COMPLEX0_H
#include<iostream>
class complex
{
private:
double real;
double img;
public:
complex();
complex(double r, double i);
~complex();
complex operator (const complex & c) const;
complex operator-(const complex & c) const;
complex operator*(const complex & c) const;
complex operator*(double n) const;
complex operator~() const;
friend complex operator*(double n, const complex &c);
friend std::istream & operator>>(std::istream & is, complex & c);
friend std::ostream & operator<<(std::ostream & os, const complex & c);
};
#endif // COMPLEX0_H
complex0.cpp:
代码语言:c 复制#include "complex0.h"
complex::complex()
{
real = img = 0;
}
complex::complex(double r, double i)
{
real = r;
img = i;
}
complex::~complex(){};
complex complex::operator (const complex & c) const
{
complex sum;
sum.real = real c.real;
sum.img = img c.img;
return sum;
}
complex complex::operator-(const complex & c) const
{
complex diff;
diff.real = real - c.real;
diff.img = img - c.img;
return diff;
}
complex complex::operator*(const complex & c) const
{
complex multi;
multi.real = real * c.real - img * c.img;
multi.img = real * c.img img * c.real;
return multi;
}
complex complex::operator*(double n) const
{
complex multi;
multi.real = real * n;
multi.img = img * n;
return multi;
}
complex complex::operator~() const
{
complex conj;
conj.real = real;
conj.img = -img;
return conj;
}
complex operator*(double n, const complex &c)
{
return c * n;
}
std::istream & operator>>(std::istream & is, complex & c)
{
std::cout << "real: ";
is >> c.real;
std::cout << "imaginary: ";
is >>c.img;
return is;
}
std::ostream & operator<<(std::ostream & os, const complex & c)
{
os << "(" << c.real << ", " << c.img << "i)";
return os;
}