
这是一个定义的一个矢量类, 然后用矢量类模拟一个酒鬼的随机漫步
问题很简单, 实现也不麻烦, 但是这个小程序却可以呈现出许多语法知识。而且代码风格也不错,因此保存在了这篇博客中。
建议:
1. 类的声明以及函数的声明放到一个文件夹内, 并且在一些必要的地方加上注释!
2. 函数的实现放到另一个文件内。
3. 将程序要具体解决的问题放到另外的一个文件里。(详见代码!)
好处: 把类的接口和实现细节分离开, 易于更改某个函数的功能。
把函数的声明和定义分开, 提高代码可读性。
把类的声明和定义 与 要解决的问题分开, 提高,类的重用性!
定义类(声明类内的函数)
// 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 in degrees double ang;// direction of vector in degrees 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() 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
上面代码涵盖了许多关于类的基础知识: 名称空间与作用域 , 实现类内部常量的方法, 构造函数, 析构函数, 运算符重载, 友元函数, 关于多种实现方法等。
PS: 实现类内部常量的方法: (1)枚举类型。 (2) static const int 常量
运算符重载: 注意操作数的顺序。
函数定义
// vect.cpp -- methods for the Vector class #include <cmath> #include "vect.h" // include <iostream> using std::sqrt; using std::sin; using std::cos; using std::atan; using std::atan2; using std::cout; namespace VECTOR { // compute degree in one radian const double Rad_to_deg = 45.0/atan(1.0); // should be about 57.2957795130823 // private methods // calculate 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 coodinate 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.0"; mode = RECT; } } // reset vector from rectangular coodinates 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/Rad_to_deg; set_x(); set_y(); } else { cout << "Incorrect 3rd argument to Vector() -- "; cout <<"vector set to 0.0 "; 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 -- using the Vector class // compile with the vect.cpp file #include <iostream> #include <cstdlib> // rand(), srand() pototypes #include <ctime> // time() pototype #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: "; cout << result <<endl; result.polar_mode(); cout << "or " << 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! "; cin.clear(); while(cin.get() != ' ') continue; return 0; }
二。一个简易的string类。
锻炼内容:
拷贝构造函数(深拷贝与浅拷贝)
重载赋值运算符(深赋值)
许多的细节与技巧!
类的声明

//sting1.h -- fixed and augmented string class definition #ifndef STRING1_H_ #define STRING1_H_ #include <iostream> using std::ostream; using std::istream; class String { private: char * str; // pointer ot string int len; // length of string static int num_strings; // number of objects static const int CINLIM = 80; // cin input limit public: // construction and other methods String(const char * s); // constructor String(); // default constructor String(const String &); // copy constructor ~String(); // destructor int length() const { return len; } // overloaded operator methods String & operator=(const String &); String & operator=(const char *); char & operator[](int i); const char & operator[](int i)const; // overloaded operator friends friend bool operator<(const String &st, const String &st2); friend bool operator>(const String &st1, const String &st2); friend bool operator==(const String &st, const String &st2); friend ostream & operator<<(ostream & os, const String & st); friend istream & operator>>(istream & is, String & st); //static function static int HowMany(); }; #endif
类方法的实现。

// string1.cpp -- String class methods #include <cstring> // string.h for some #include "string1.h" // includes <iostream> using std::cin; using std::cout; // initializing static class member int String::num_strings = 0; // static method int String::HowMany() { return num_strings; } // class methods String::String(const char * s) // construct String from C string { len = std::strlen(s); // set size str = new char[len + 1]; // allot storage std::strcpy(str, s); // initialize pointer num_strings++; // set object count } String::String() // default constructor { len = 4; str = new char[1]; str[0] = '