C++ Primer Plus习题及答案-第十一章

习题选自:C++ Primer Plus(第六版)
内容仅供参考,如有错误,欢迎指正 !
文章首发微信公众号:iDoitnow

  • 一般来说,访问私有成员的唯一方法是使用类方法,c++使用友元函数来避开这种限制,要让函数成为友元,需在类声明中声明该函数,并在声明前加上关键字friend。
  • 运算符函数可以是类成员函数,也可以是友元函数(有一些运算符函数只能是类成员函数),如果要使其第一个操作数不是类对象,则必须使用友元函数,这样就可以将操作数按所需的顺序传递给函数了。

复习题

1.使用成员函数Stonewt类重载乘法运算符,该运算符将数据成员与double类型的值相乘。注意使用英石和磅表示时,需要进位。也就是说,将10英石8磅乘以2等于21英石2磅(1 英石=14 磅)。
Stonewt Stonewt::operator*(double a)
{
    this->stone=this->stone*a+this->pounds*a/14;
    this->pounds=(this->pounds*a)%14;
    return *this;
}
2.友元函数和成员函数之间的区别是什么?

成员函数是类定义的一部分,通过特定的对象来调用。成员函数可以隐式访问调用对象的成员,而无需使用成员运算符。友元函数不是类的组成部分,因此被称为直接函数调用。友元函数不能隐式访问类成员,而需要将成员运算符用作参数传递的对象。

3.非成员函数必须是友元才能访问类成员吗?

要访问私有成员,它必须是友元,但要访问共有成员,可以不是友元。

4.使用友元函数为Stonewt类重载乘法运算符,该运算符将double值与Stone值相乘。
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类型的值,后者表示矢量的长度。
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:

// vect.h -- Vector class with <<, mode state
#ifndef VECTOR_H_
#define VECTOR_H_
#include 
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:

// vect.cpp -- methods for the Vector class
#include 
#include "vect.h"   // includes 
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 0\n";
             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 0\n";
             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:

// randwalk.cpp -- using the Vector class
// compile with the vect.cpp file
#include 
#include       // rand(), srand() prototypes
#include         // time() prototype
#include "vect.h"
#include 
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 << " or\n" << 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 << " or\n" << 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:

// vect.h -- Vector class with <<, mode state
#ifndef VECTOR_H_
#define VECTOR_H_
#include 
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:

// vect.cpp -- methods for the Vector class
#include 
#include "vect.h"   // includes 
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 0\n";
             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 0\n";
             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:

// randwalk.cpp -- using the Vector class
// compile with the vect.cpp file
#include 
#include       // rand(), srand() prototypes
#include         // 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 << " or\n" << 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:

// vect.h -- Vector class with <<, mode state
#ifndef VECTOR_H_
#define VECTOR_H_
#include 
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:

// vect.cpp -- methods for the Vector class
#include 
#include "vect.h"   // includes 
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 0\n";
             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 0\n";
             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:

// randwalk.cpp -- using the Vector class
// compile with the vect.cpp file
#include 
#include       // rand(), srand() prototypes
#include         // 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:

// mytime3.h -- Time class with friends
#ifndef MYTIME3_H_
#define MYTIME3_H_
#include 

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:

// 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:

//usetime3.cpp -- using the fourth draft of the Time class
// compile usetime3.cpp and mytime3.cpp together
#include 
#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:

// stonewt.h -- definition for the Stonewt class
#ifndef STONEWT_H_
#define STONEWT_H_
#include

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:

// stonewt.cpp -- Stonewt methods
#include 
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:

#include "stonewt.h"
#include 

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:

// 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:

// stonewt.cpp -- Stonewt methods
#include 
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 << " pounds\n";
}

// show weight in pounds
void Stonewt::show_lbs() const
{
    cout << pounds << " pounds\n";
}


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:

#include "stonewt.h"
#include 

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
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:

#ifndef COMPLEX0_H
#define COMPLEX0_H
#include

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:

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

你可能感兴趣的:(C++,Primer,Plus习题及答案,c++,开发语言)