c++入門之 再話類
阿新 • • 發佈:2018-11-11
對於類,其結構並不難,但要理解其設計思想也並不容易,在此,我們可以通過下面的程式碼進一步理解和使用類:
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 doublemagval() 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\n"; 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\n"; 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中,但友元函式並不在類作用域中!!! 這對於所有友元函式都成立!!!