对于类,其结构并不难,但要理解其设计思想也并不容易,在此,我们可以通过下面的代码进一步理解和使用类:
1 # ifndef VECTOR_H_ 2 # define VECTOR_H_ 3 # include "iostream" 4 5 namespace VECTOR //注意,这里对这个类定义了名称空间,实际上,在写自己的类时,也应该定义自己的名称空间 6 { 7 class Vector 8 { 9 public: 10 enum Mode{RECT,POL};//因为这个量需要用户自己去设定 11 private: //注意:私有成员(无论是函数还是变量)只能被类内部成员访问 12 double x; 13 double y; 14 double mag; 15 double ang; 16 Mode mode; 17 18 void set_mag(); 19 void set_ang(); 20 void set_x(); 21 void set_y(); //体会将这些函数放在这里的用意!! 22 public: //共有成员可以被所有访问!!理解这个意思 23 Vector();//构造函数 24 Vector(double n1,double n2,Mode form = RECT);//注意,这里有默认参数 25 void reset(double n1, double n2, Mode form = RECT); 26 ~Vector();//析构函数 27 double xval() const{ return x; } 28 double yval() const{ return y; } 29 double magval() const{ return mag; } 30 double angval() const{ return ang; } 31 void polar_mode(); 32 void rect_mode(); 33 34 Vector operator+(const Vector &b) const; 35 Vector operator-(const Vector &b) const; 36 Vector operator-() const; 37 Vector operator*(double n) const; 38 39 friend Vector operator*(double n, const Vector &a);//注意这里采用了友元函数的做法,应该显示包含所有参数 40 friend std::ostream & operator<<(std::ostream &os, const Vector & v);//昨天没有思考返回引用是否存在问题???因为局部变量被销毁的问题 41 }; 42 43 } 44 # endif
该类定义中:除了备注的一些以外,总结这么几点:
1 定义了一个类的时候,限定了该类的名称空间通常是一件好事,以免自己的变量和别人的发生了冲突
2 公有还是私有并无界限之分,完全取决于程序的功能。
3 我们通常会发现:当定义一个类成员函数时,通常需要:构造函数,析构函数,甚至友元函数
4 私有成员(无论是变量还是函数)只能被类内部的成员进行访问,而共有成员 可以被其他类甚至其他任何东西访问。究其本质:公有部分 是提供的接口
下面给出该定义:
1 # include"cmath" //从下文的调用方法来看,这里应该是函数库,而不是类库 2 # include "vector.h" 3 using std::sqrt; //注意 std 包含了很多 4 using std::sin; 5 using std::cos; 6 using std::atan; 7 using std::atan2; 8 using std::cout; 9 10 namespace VECTOR //名称空间的意义是很有必要的 11 { 12 const double Rad_to_deg = 45.0 / atan(1.0); 13 void Vector::set_ang() 14 { 15 mag = sqrt(x*x + y*y); //求极长 16 } 17 18 void Vector::set_ang() 19 { 20 if (x == 0.0 && y == 0.0) 21 ang = 0.0; 22 else 23 ang = atan2(y, x);//求极角 24 } 25 26 void Vector::set_x() //这些是私有函数 27 { 28 x = mag*cos(ang);//私有函数可以访问私有变量表明私有成员也可以相互访问 29 } 30 31 void Vector::set_y() 32 { 33 y = mag*sin(ang); 34 } 35 36 Vector::Vector() 37 { 38 x = y = mag = ang = 0.0; 39 mode = RECT; 40 } 41 42 Vector::Vector(double n1, double n2, Mode form) 43 { 44 mode = form; 45 if (form == RECT) 46 { 47 x = n1; 48 y = n2; 49 set_mag();//访问了私有成员 50 set_ang();//体会这里的设计思想 51 } 52 else if (form == POL) 53 { 54 mag = n1; 55 ang = n2; 56 set_x(); 57 set_y(); 58 } 59 else 60 { 61 cout << "Incorrect 3rd argument to Vector()--"; 62 cout << "vector set to 0 "; 63 x = y = mag = ang = 0.0; 64 mode =RECT; 65 } 66 } 67 void Vector::reset(double n1, double n2, Mode form) 68 { 69 mode = form; 70 if (form = RECT) 71 { 72 x = n1; 73 y = n2; 74 set_mag(); 75 set_ang(); 76 } 77 else if (form = POL) 78 { 79 mag = n1; 80 ang= n2; 81 set_x(); 82 set_y(); 83 } 84 else 85 { 86 cout << "Incorrect 3rd argument to Vector()--"; 87 cout << "vector set to 0 "; 88 x = y = mag = ang = 0.0; 89 mode = RECT; 90 } 91 } 92 Vector::~Vector()// 93 { 94 95 } 96 97 void Vector::polar_mode() 98 { 99 mode = POL; 100 } 101 102 void Vector::rect_mode() 103 { 104 mode = RECT; 105 } 106 107 Vector Vector::operator+(const Vector &b) const 108 { 109 return Vector(x + b.x, y + b.y); 110 } 111 112 Vector Vector::operator-(const Vector &b) const 113 { 114 return Vector(x - b.x, y - b.y); 115 } 116 117 Vector Vector::operator-() const 118 { 119 return Vector(-x, -y); 120 } 121
Vector Vector::operator*(double n) const
{
return(n*x,x*y)
}
122 Vector operator*(double n, const Vector & a) 123 { 124 return a*n; //注意,虽然这里进行了返回,但并没有结束,而是继续调用了成员函数, 125 } 126 127 std::ostream & operator<<(std::ostream & os, const Vector & v) 128 { 129 if (v.mode == Vector::RECT) 130 os << "(x,y) = (" << v.x << "," << v.y << ")"; 131 else if (v.mode == Vector::POL) 132 { 133 os << "(m,a) = (" << v.mag << "," << v.ang + Rad_to_deg << ")"; 134 } 135 else 136 os << "Vector object mode is invalid"; 137 } 138 }
1. 我们注意107行和112行的代码:本质上,进行了加法和减法之后,得到的是一个新的类对象,但由于这个类对象不止一种表示形式(直角坐标和极坐标),这里巧妙的利用了 返回构造函数的执行。这告诉我们:构造函数并不仅仅用于初始化,构造函数的本意:构造新的对象,一定要认识这一本质特征和思想。
2 我们注意124行的代码:return a*n; 本质上,对象乘以一个数无法实现,但这里,其实,并没有返回,而是回去重新调用了上面的*。
3 注意:129行和131行:if (v.mode == Vector::RECT)。为何要加Vector::RECT而不是RECT,这是因为:
友元函数虽然在public中,但友元函数并不在类作用域中!!! 这对于所有友元函数都成立!!!