复习题
#pragma once//避免此头文件被包含多次,和#ifndef的作用类似 //11.8 //1 Stonewt operator*(double mult);//原型 Stonewt Stonewt::operator*(double mult) { return Stonewt(mult * pounds); } //2 成员函数是类定义的一部分,通过特定的对象来调用。成员函数可以隐式地访问调用对象的成员, 而无需使用成员运算符。友元函数不是类的组成部分,因此被称为直接函数调用。友元函数不能 隐式地访问类成员,必须将成员运算符用于作为参数传递的对象。可比较复习题1和4 //3 要访问私有成员,必须是友元,要访问公有成员,可以不是友元 //4 friend Stonewt operator*(double mult, const Stonewt& w);//原型 Stonewt operator*(double mult, const Stonewt& w) {//函数定义 return Stonewt(mult * w.pounds); } //5 \sizeof\.\.*\::\ ? : \ \typeid\const_cast\dynamic_cast\reinterpret_cast\static_cast\ //6 这些运算符必须使用成员函数定义 //7 operator double()const { return mag; }
practice 1
找不到程序清单复制粘贴,就很难受
//vect.h -- Vector class with <<,mode state #pragma once//避免此头文件被包含多次,和#ifndef的作用类似 #ifndef VECT_H_ #define VECT_H_ #include<iostream> namespace VECTOR { class Vector { public: enum Mode{RECT,POL}; //RECT for rectangular,POL for Polar modes private: double x; double y; double mag; double ang; Mode mode; //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() { return x; } double yval() { return y; } double magval() { return mag; } double angval() { return ang; } void polar_mode(); void rect_mode(); //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 -- methods for the Vector class #include<cmath> #include"vect.h" 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 method //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 metohds Vector::Vector() { 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; set_x(); set_y(); } else { cout << "Incorrent 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 form 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; set_x(); set_y(); } else { cout << "Incorrent 3rd argument to Vector() -- "; cout << "Vector set to 0\n"; x = y = mag = ang = 0.0; mode = RECT; } } Vector::~Vector() { } void Vector::polar_mode() { mode = POL; } void Vector::rect_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, Vector& a) { return a * n; } //display rectangular coordinate 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 -- suing the Vector class //compile with the vect.cpp file #include<iostream> #include<cstdlib> #include<ctime> #include"vect.h" #include<fstream> int main() { using namespace std; using namespace VECTOR; srand(time(0)); double direction;//方向:角度 Vector step;//创建类矢量:每一步 Vector result(0, 0);//结果:累积矢量 unsigned long steps = 0;//步数 double target = 100;//目标距离 double dstep = 20;//每一步长度 ofstream fout; fout.open("jieguo.txt"); fout << "Target Distance: " << target << ", Step Size: " << dstep << endl; fout << steps << ": " << result << endl; while (result.magval() < target) { direction = rand() % 360; step.reset(dstep, direction, Vector::POL); result = result + step; steps++; fout << steps << ": " << result << endl; } fout << "After " << steps << " steps,the subject " << "has the following location:\n"; fout << result << endl; result.polar_mode(); fout << " or " << endl << result << endl; fout << "Average outward distance per step = " << result.magval() / steps << endl; fout << "Bye!\n"; return 0; }
运行结果如下:
编辑
practice 2
针对practice 1的答案做如下修改,因为不能存储mag和ang
1,因此要更改四个计算x,y,mag,ang的私有方法,前两个要返回double值以使用,后两个要传递两个double参数。
2,公有方法里的返回mag和ang值的内联函数magval(),angval()需要修改,在main里面会用到。
3,显然构造函数也需要对应的修改。
4,修改reset(),与带参数的构造函数一致。
5,最后修改<<运算符的重载函数,这里可能出现错误
E1086 对象含有与成员 函数 "VECTOR::Vector::angval" 不兼容的类型限定符。有两种可能
1)const对象只能调用const函数
2)const函数中不小心修改了类成员或者调用了非常量函数
因为要显示mag和ang用到了修改后的set_mag(),set_ang(),这两个函数进行了运算不是常量函数
所以去掉参数列表的const就可以了,注意原型的const也要去掉,不然就会有各种奇奇怪怪的错误
6,最后把randwalk.cpp的代码改成和程序清单11.15完全一样就可以了。
//vect.h -- Vector class with <<,mode state #pragma once//避免此头文件被包含多次,和#ifndef的作用类似 #ifndef VECT_H_ #define VECT_H_ #include<iostream> namespace VECTOR { class Vector { public: enum Mode{RECT,POL}; //RECT for rectangular,POL for Polar modes private: double x; double y; Mode mode; //Private methods for setting values double set_mag(); double set_ang(); double set_x(double mag,double ang); double set_y(double mag,double ang); public: Vector(); Vector(double n1, double n2, Mode form = RECT); void reset(double n1, double n2, Mode form = RECT); ~Vector(); double xval() { return x; } double yval() { return y; } double magval() { return set_mag(); } double angval() { return set_ang(); } void polar_mode(); void rect_mode(); //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, Vector& v); }; }//end namespace VECTOR #endif //vect.cpp -- methods for the Vector class #include<cmath> #include"vect.h" 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 method //calculates magnitude from x and y double Vector::set_mag() { return sqrt(x * x + y * y); } double Vector::set_ang() { if (x == 0.0 && y == 0.0) return 0.0; else return atan2(y, x); } //set x from polar coordinate double Vector::set_x(double mag, double ang) { return x = mag * cos(ang); } //set y from polar coordinate double Vector::set_y(double mag, double ang) { return y = mag * sin(ang); } //public metohds Vector::Vector() { 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) { set_x(n1,n2); set_y(n1,n2); } else { cout << "Incorrent 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 form 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) { set_x(n1, n2); set_y(n1, n2); } else { cout << "Incorrent 3rd argument to Vector() -- "; cout << "Vector set to 0\n"; x = y = 0.0; mode = RECT; } } Vector::~Vector() { } void Vector::polar_mode() { mode = POL; } void Vector::rect_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, Vector& a) { return a * n; } //display rectangular coordinate if mode is RECT //else display polar coordinates if mode is POL std::ostream& operator<<(std::ostream& os, Vector& v) { if (v.mode == Vector::RECT) os << "(x,y) = (" << v.x << "," << v.y << ")"; else if (v.mode == Vector::POL) os << "(m,a) = " << "(" << v.set_mag() << ", " << v.set_ang() * Rad_to_deg << ")"; else os << "Vector object mode is invalid."; return os; } }//end namespace VECTOR //randwalk.cpp -- suing the Vector class //compile with the vect.cpp file #include<iostream> #include<cstdlib> #include<ctime> #include"vect.h" #include<fstream> int main() { using namespace std; using namespace VECTOR; srand(time(0)); double direction;//方向:角度 Vector step;//创建类矢量:每一步 Vector result(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); cout << "Enter target distance (q to quit): "; } cout << "Bye!"; cin.clear(); while (cin.get() != '\n') continue; return 0; }
practice 3
这题还是用原来的vect.h和vect.cpp,所以就不重复发代码了,直接复制practice 1,和书上的程序清单完全一致,抄了我半天。
这里我把vect.h里面类声明里面的enum改成了enum class,因为一直有警告要求首选enum class,注意把后面的RECT,POL加上限定符Mode::
//randwalk.cpp -- suing the Vector class //compile with the vect.cpp file #include<iostream> #include<cstdlib> #include<ctime> #include"vect.h" #include<fstream> int main() { using namespace std; using namespace VECTOR; srand(time(0)); double direction;//方向:角度 Vector step;//创建类矢量:每一步 Vector result(0, 0);//结果:累积矢量 unsigned long steps = 0;//步数 double target;//目标距离 double dstep;//每一步长度 int N;//执行次数 cout << "Enter target distance (q to quit): "; cin >> target; cout << "Enter step length: "; cin >> dstep; cout << "Enter the execution times: "; cin >> N; unsigned long max = 0; unsigned long min = 0; unsigned long total = 0; for (int i = 0; i < N; i++) { while (result.magval() < target) { direction = rand() % 360; step.reset(dstep, direction, Vector::Mode::POL); result = result + step; steps++; } if (i == 0) max = min = steps; else { if (steps > max) max = steps; if (steps < min) min = steps; total += steps; } steps = 0; result.reset(0.0, 0.0); } cout << "Report the result of tests: " << "The maximum steps: " << max << endl << "The minimum steps: " << min << endl << "The average steps: " << double(total)/N << endl; cout << "Bye!"; return 0; }
practice 4
//mytime.h -- Time class with friends #pragma once//避免此头文件被包含多次,和#ifndef的作用类似 #ifndef MYTIME_H_ #define MYTIME_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, const double n); friend Time operator*(const double n, const Time& t) { return t * n; } friend std::ostream& operator<<(std::ostream& os, const Time& t); }; #endif //mytime.cpp -- implementing Time methods #include"mytime.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 time; time.minutes = t1.minutes + t2.minutes;; time.hours = t1.hours + t2.hours + time.minutes / 60; time.minutes %= 60; return time; } Time operator-(const Time& t1, const Time& t2) { Time time; int tot1, tot2; tot1 = t1.minutes + t1.hours * 60; tot2 = t2.minutes + t2.hours * 60; time.hours = (tot1 - tot2) / 60; time.minutes = (tot1 - tot2) % 60; return time; } Time operator*(const Time& t, double n) { Time time; long totalminutes = t.hours * 60 * n + t.minutes * n; time.hours = totalminutes / 60; time.minutes = totalminutes % 60; return time; } std::ostream& operator<<(std::ostream& os, const Time& t) { os << t.hours << " hours, " << t.minutes << " minutes"; return os; } //usetime.cpp -- using the Time class //compile with the mytime.cpp file #include<iostream> #include"mytime.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; 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; }
practice 5
//stonewt.h -- definition for the Stone class #pragma once//避免此头文件被包含多次,和#ifndef的作用类似 #ifndef STONEWT_H_ #define STONEWT_H_ #include<iostream> class Stonewt { public: enum class Mode { STN, PDS_INT, PDS }; private: enum { Lbs_per_stn = 14 }; int stone; double pds_left; double pounds; int pds_int; Mode mode; void pds_stn(){ stone = pounds / Lbs_per_stn; pds_left = pounds - stone * Lbs_per_stn; } void pds_pdsint() { pds_int = int(pounds); } void stn_pds() { pounds = stone * Lbs_per_stn + pds_left; } public: Stonewt(double pds); Stonewt(int stn, double pdsl); Stonewt(); ~Stonewt(); Stonewt operator + (const Stonewt & s)const; Stonewt operator - (const Stonewt & s)const; Stonewt operator * (double mul)const; void mode_STN() { mode = Mode::STN; } void mode_PDS() { mode = Mode::PDS; } void mode_PDS_INT() { mode = Mode::PDS_INT; } friend Stonewt operator*(double mult, const Stonewt& s) { return s * mult; } friend std::ostream& operator<<(std::ostream& os, const Stonewt& s); }; #endif //stonewt.cpp -- implementing Stonewt methods #include"stonewt.h" #include<iostream> Stonewt::Stonewt(double pds) { pounds = pds; pds_stn(); pds_pdsint(); mode = Mode::PDS; } Stonewt::Stonewt(int stn, double pdsl) { stone = stn; pds_left = pdsl; stn_pds(); pds_pdsint(); mode = Mode::STN; } Stonewt::Stonewt() { pounds = stone = pds_left = 0; pds_int = 0; mode = Mode::PDS; } Stonewt::~Stonewt(){} Stonewt Stonewt::operator + (const Stonewt& s)const { Stonewt swt; swt.pounds = pounds + s.pounds; return Stonewt(swt.pounds); } Stonewt Stonewt::operator - (const Stonewt& s)const { Stonewt swt; swt.pounds = pounds - s.pounds; return Stonewt(swt.pounds); } Stonewt Stonewt::operator * (double mult)const { Stonewt swt; swt.pounds = pounds * mult; return Stonewt(swt.pounds); } std::ostream& operator<<(std::ostream& os, const Stonewt& s) { if (s.mode == Stonewt::Mode::PDS) os << "Mode: PDS: " << s.pounds << " pounds"; else if (s.mode == Stonewt::Mode::STN) os << "Mode: STN: " << s.stone << " stones, " << s.pds_left << "pounds"; else if (s.mode == Stonewt::Mode::PDS_INT) os << "Mode: PDS_INT: " << s.pds_int << " pounds"; else os << "The mode of Stonewt is wrong!"; return os; } //main.cpp #include<iostream> #include"stonewt.h" int main() { using std::cout; using std::endl; Stonewt s1; Stonewt s2(321.123); Stonewt s3(10, 12.5); cout << s1 << endl << s2 << endl << s3 << endl; cout << "s2-s3= " << s2 - s3 << endl; cout << "s2+s3= " << s2 + s3 << endl; s1 = s3 * 13.5; cout << "s3*13.5= " << s1 << endl; s1 = 13.5 * s3; s1.mode_PDS_INT(); cout << "13.5*s2= " << s1 << endl; s1.mode_STN(); cout << "13.5*s2= " << s1 << endl; return 0; }
编辑
practice 6
不能怪我懒,主要是抄代码实在太费时间了,所以直接用上一题的代码好了
贴太多代码看着都麻烦,所以只贴增加的一部分
//add to stonewt.h bool operator>(const Stonewt& s); bool operator>=(const Stonewt& s); bool operator<(const Stonewt& s); bool operator<=(const Stonewt& s); bool operator==(const Stonewt& s); bool operator!=(const Stonewt& s); //add to stonewt.cpp bool Stonewt::operator>(const Stonewt& s) { if (pounds > s.pounds) return true; else return false; } bool Stonewt::operator>=(const Stonewt& s) { if (pounds >= s.pounds) return true; else return false; } bool Stonewt::operator<(const Stonewt& s) { if (pounds < s.pounds) return true; else return false; } bool Stonewt::operator<=(const Stonewt& s) { if (pounds <= s.pounds) return true; else return false; } bool Stonewt::operator==(const Stonewt& s) { if (pounds == s.pounds) return true; else return false; } bool Stonewt::operator!=(const Stonewt& s) { if (pounds != s.pounds) return true; else return false; } //main.cpp #include<iostream> #include"stonewt.h" int main() { using std::cout; using std::cin; using std::endl; Stonewt arr_s[6] = { 12.3,14.5,17.8 }; Stonewt standard(11); for (int i = 0; i < 3; i++) { cout << "Enter three number to construct Stonewt:\n"; cout << "#" << i + 3 << ": "; double pds; cin >> pds; arr_s[i + 3] = Stonewt(pds); } for (int i = 0; i < 6; i++) { cout << "arr_s[" << i << "]: " << arr_s[i] << endl; } int max = 0; int min = 0; int n = 0; for (int i = 0; i < 6; i++) { if (arr_s[max] < arr_s[i]) max = i; if (arr_s[min] > arr_s[i]) min = i; if (arr_s[i] >= standard) n++; } cout << "The heaviest is arr_s[" << max << "]\n" << "The lightest is arr_s[" << min << "]\n" << "The number of Stonewts not ligther than 11 pounds is " << n << endl; return 0; }
practice 7
这题我在自定义构造函数前没有用explicit,而且第二个参数是有默认参数,但是重载*的函数中2*c的函数我写了一个return c*2; 它不能自动转换,必须加(complex),就很奇怪,有没有懂的评论一下
//complex0.h #pragma once//避免此头文件被包含多次,和#ifndef的作用类似 #ifndef COMPLEX0_H_ #define COMPLEX0_H_ #include<iostream> class complex { private: double real; double imaginary; public: complex(); complex(double rl, double imgnr = 0); complex operator+(const complex& c)const; complex operator-(const complex& c)const; complex operator*(const complex& c)const; complex operator~()const; friend complex operator*(double n,const complex& c); friend std::istream& operator>>(std::istream& os, complex& c); friend std::ostream& operator<<(std::ostream& os, const complex& c); }; #endif //complex0.cpp #include"complex0.h" complex::complex() { real = imaginary = 0.0; } complex::complex(double rl, double imgnr) { real = rl; imaginary = imgnr; } complex complex::operator+(const complex& c)const { complex sum; sum.real = real + c.real; sum.imaginary = imaginary + c.imaginary; return sum; } complex complex::operator-(const complex& c)const { complex sub; sub.real = real - c.real; sub.imaginary = imaginary - c.imaginary; return sub; } complex complex::operator*(const complex& c)const { complex mult; mult.real = real * c.real - imaginary * c.imaginary; mult.imaginary = real * c.imaginary + imaginary * c.real; return mult; } complex complex::operator~()const { complex conjugate; conjugate.real = real; conjugate.imaginary = imaginary; return conjugate; } complex operator*(double n, const complex& c) { return c * n; } std::istream& operator>>(std::istream& is, complex& c) { std::cout << "real: "; is >> c.real; if (is) { std::cout << "imaginary: "; is >> c.imaginary; } return is; } std::ostream& operator<<(std::ostream& os, const complex& c) { os << "(" << c.real << "," << c.imaginary << "i)"; return os; } //main.cpp #include<iostream> #include"complex0.h" int main() { using std::cout; complex a(3.0, 4.0); complex c; cout << "Enter a complex number (q to quit): \n"; while (std::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; }
为了搞清楚,我又双叒叕把(complex)去掉了,结果居然运行成功了