430 likes | 616 Views
12.1 多載概論 12-2 12.1.1 多載一般函數 12-2 12.1.2 多載成員函數 12-3 12.1.3 多載建立者函數 12-5 12.2 多載運算符號 12-8 12.2.1 多載運算符號限制 12-9 12.2.2 運算符號函數 12-12 12.2.3 多載 >> 運算符號 12-12 12.2.4 多載 << 運算符號 12-13 12.2.5 多載雙運算元符號 12-16 12.2.6 多載單運算元符號 12-20.
E N D
12.1多載概論 12-2 12.1.1 多載一般函數 12-2 12.1.2 多載成員函數 12-3 12.1.3 多載建立者函數 12-5 12.2多載運算符號 12-8 12.2.1 多載運算符號限制 12-9 12.2.2 運算符號函數 12-12 12.2.3 多載 >> 運算符號 12-12 12.2.4 多載 << 運算符號 12-13 12.2.5 多載雙運算元符號 12-16 12.2.6 多載單運算元符號 12-20 12.2.7 多載前置運算符號 12-23 12.2.8 多載後置運算符號 12-23 12.3轉換型態 12-26 12.3.1 基本型態轉基本型態 12-26 12.3.2 基本型態轉類別型態 12-27 12.3.3 類別型態轉基本型態 12-29 12.3.4 類別型態轉類別型態 12-31 12 多載函數
12.1 多載概論 • 多載(overloading)就是重複定義多個相同名稱的函數,但這些函數的功能不完全相同。所以多載函數的情況包括:(1)接收不同數量的參數,(2)傳遞不同型態的參數,(3)傳回不同型態的參數。
12.1.1 多載一般函數 • 範例 int area(int length, int width); //第一個area { return length * width; } double area(int radius) //第二個area函數 { return 3.1415926 * pow(radius, 2); } int main() { int rectangleArea = area(3, 5); //呼叫第一個area函數 double circleArea = area(5); //呼叫第二個area函數 return 0; //正常結束程式 }
12.1.2 多載成員函數 • 多載函數的情況包括:(1)接收不同數量的參數,(2)傳遞不同型態的參數,(3)傳回不同型態的參數。 • 範例一 class Cuboid //宣告長方體類別 { private: int length; //Cuboid的資料成員1 int width; //Cuboid的資料成員2 int height; //Cuboid的資料成員3
12.1.2 多載成員函數 (續) • 範例續 public: int area() { //錯誤,Multiple declaration return length * width; } int area() { //錯誤,Multiple declaration return 2 * (length * width + width * height + height * length); } };
12.1.2 多載成員函數 (續) • 範例二 class Cuboid //宣告長方體類別 { int length; //Cuboid的資料成員1 int width; //Cuboid的資料成員2 int height; //Cuboid的資料成員3 public: void setSide(int l, int w) //設定長方形邊長 { length = l; width = w; height = 0; }
12.1.2 多載成員函數 (續) • 範例續 void setSide(int l, int w, int h) //設定長方體邊長 { length = l; width = w; height = h; } int area() //計算長方體表面積函數 { return 2 * (length * width + width * height + height * length); } };
12.1.3 多載建立者函數 • 在類別中可以多載(overload)建立者函數,也就是定義多個建立者函數,每個建立者函數可含有不同個數的參數。 • 範例 class Timer { int seconds; public: Timer() { //定義無參數建立者 seconds = 0;} Timer(int s) { //定義整數參數建立者 seconds = s;}
12.1.3 多載建立者函數 (續) • 範例續 Timer(char *t) { //定義指標參數建立者 seconds = atoi(t);} }; int main() { char str[20] = "250"; Timer t1; //t1.seconds = 0 Timer t2(10); //t2.seconds = 10 Timer t3(str); //t3.seconds = 250 return 0; //正常結束程式 }
Exercise • 建立一個Circle類別 • 定義private資料成員radius • 定義無參數建立者函數,設定radius=1 • 定義一個參數建立者函數,設定radius=參數 • 定義public成員函數area,計算圓面積 • 撰寫main()函數,宣告兩個Circle的物件變數,一個有參數,另一無參數,分別呼叫area函數後印出各自的圓面積
12.2 多載運算符號 • 在C++ 語言中,<< 運算符號可以配合cout敘述作為字串輸出運算符號,也可以作為左移位元運算符號;同理,>> 運算符號可以配合cin敘述作為字串輸入運算符號,也可以作為右移位元運算符號。這就是運算符號多載(operator overloading)。 • 運算符號多載(operator overloading),就是要再定義這些運算符號,使它們也能接受使用者自定的資料型態與物件。
12.2.1 多載運算符號限制 • 可以被多載的運算符號包括表12.1算術運算符號、表12.2關係與邏輯運算符號、表12.3位元運算符號、表12.4指定運算符號、表12.5特殊運算符號。 • 表中同時提供這些運算符號在C++ 的內建功能、範例與說明,設計師為自定資料型態多載這些符號時,必須保持它們原來的功能,否則將會造成語法錯誤訊息。 • 例如,將 + 多載為減法運算符號,編譯時會出現語法錯誤訊息。
12.2.2 運算符號函數 • 運算符號函數可以是類別成員函數或非類別成員函數。當非成員函數或非friend函數要存取私用區(private)或保護區(protected)的資料時,必須先呼叫公用區(public)的set或get成員函數,如此將會降低程式的性能。 • 所以為了得到更好的性能,可使用friend函數,friend雖然不是類別成員函數但仍可直接存取私用區(private)或保護區(protected)的資料。
12.2.3 多載 >> 運算符號 • friend istream &operator>>(istream&傳回參數, 類別名稱 物件參數) • 範例 class Test { private: int a, b; //定義private變數 public: Test() { a = b = 0; }
12.2.3 多載 >> 運算符號 (續) • 範例續 Test(int n, int m) { a = n; b = m; } }; int main() { Test s1; cin >> s1; //錯誤不能輸入Test型態資料 cout << s1; //錯誤不能輸出Test型態資料 return 0; //正常結束程式 }
12.2.4 多載 << 運算符號 • friend ostream &operator<<(ostream&傳回參數, 類別名稱 物件參數) • 範例 class Test { private: int a, b; //定義private變數 public: Test() { a = b = 0; }
12.2.4 多載 << 運算符號 (續) • 範例續 Test(int n, int m) { a = n; b = m; } friend istream& operator>>(istream& in, Test& obj); friend ostream& operator<<(ostream& out, Test& obj); }; istream& operator>>(istream& in, Test& obj) { cout << "請輸入a與b之值:"; in >> obj.a >> obj.b; return in; }
12.2.4 多載 << 運算符號 (續) • 範例續 ostream& operator<<(ostream& out, Test& obj) { out << "a 與 b 的值:" << endl; out << obj.a << " " << obj.b << endl; return out; } int main() { Test s1; cin >> s1; //若輸入2 3 cout << s1; //則輸出2 3 return 0; //正常結束程式 }
12.2.5 多載雙運算元符號 • 傳回型態 operator運算符號(類別型態 物件參數) • 傳回型態 operator運算符號(類別1 物件1, 類別2 物件2) • 範例 class Test { int a, b; //定義private變數 public: Test() { a = b = 0; } Test(int n, int m) { a = n; b = m; } Test operator+(Test); //宣告多載 + 號 };
12.2.5 多載雙運算元符號 (續) • 範例一續 Test Test::operator+(Test obj) { //定義多載 + 號 Test temp; temp.a = a + obj.a; //a=s1.a, obj.a=s2.a temp.b = b + obj.b; //b=s1.b, obj.b=s2.b return temp; } int main() { Test s1(2, 3), s2(4, 5), s3; s3 = s1 + s2; //s1.operator+(s2) return 0; //正常結束程式 }
12.2.5 多載雙運算元符號 (續) • 範例二 class Test { int a; //定義private變數 public: Test() { a = 0; } Test(int n) { a = n; } bool operator>(Test); //宣告多載 > 號 }; bool Test::operator>(Test obj) { //定義多載 > 號 if (a > obj.a) return true; else return false; }
12.2.5 多載雙運算元符號 (續) • 範例二續 int main() { Test s1(2), s2(5); if (s1 > s2) //呼叫多載 > 函數 cout << "s1 > s2"; else cout << "s1 < s2"; return 0; //成功結束程式 }
12.2.6 多載單運算元符號 • 傳回型態 operator運算符號() • 傳回型態 operator運算符號(類別型態 物件參數) • 範例 class Test { int a; //定義private變數 public: Test(int n) { a = n; } bool operator !(); //宣告多載 ! 號 };
12.2.6 多載單運算元符號 (續) • 範例續 bool Test::operator!() { //定義多載 ! 號 if (a != 0) {return true;} else {return false;} } int main() { Test s1(5); if (!s1) {cout << "s1 != 0"; } //呼叫多載 ! 符號函數 else {cout << "s1 == 0";} return 0; //正常結束程式 }
12.2.7 多載前置運算符號 • 傳回型態 operator運算符號() • 範例 class Test { int a, b; //定義private變數 public: Test() { a = b = 0; } Test(int n, int m) { a = n; b = m; } Test operator++(); //宣告前置 ++x 號 };
12.2.7 多載前置運算符號 (續) • 範例續 Test Test::operator++() //定義前置 ++x 號 { return Test(++a, ++b); } int main() { Test s1(2, 3), s2; s2 = ++s1; //等於s1.operator++() return 0; //正常結束程式 }
12.2.8 多載後置運算符號 • 傳回型態 operator運算符號(int) • 範例 class Test { int a, b; //定義private變數 public: Test() { a = b = 0; } Test(int n, int m) { a = n; b = m; } Test operator++(int); //宣告後置 x++ 號 };
12.2.8 多載後置運算符號 (續) • 範例續 Test Test::operator++(int) //定義後置 x++ 號 { return Test(a++, b++); } int main() { Test s1(2, 3), s2; s2 = s1++; //s2.a=s1.a=2, s2.b=s1.b=3 //s1.a=++s1.a=3, s1.b=++s1.b=4 return 0; //正常結束程式 }
Exercise • 建立一個Counter類別 • 定義private資料成員count • 定義建立者函數並設定count=0 • 定義成員函數getcount() • 重載++ • 撰寫main()函數,宣告一個Counter的物件變數,呼叫兩次++後,印出count值
12.3.1 基本型態轉基本型態 • float型態的fracfeet轉成int型態的feet int feet; float fracfeet = 3.280833 * 3.5; feet = int(fracfeet); //float轉成int • int型態的fracfeet轉成float型態的fracfeet int feet; float fracfeet = inch / 12; fracfeet = float(feet); //feet從int轉為float
12.3.2 基本型態轉類別型態 • float型態的資料轉成Distance型態 const float MTF = 3.280833f; class Distance //宣告Distance類別 { int feet; float inch; public: Distance (int f, float in) //宣告一參數建立者 { feet = f; inch = in; }
12.3.2 基本型態轉類別型態 (續) • 範例續 Distance (float meter) { //宣告二參數建立者 float fracfeet = MTF * meter; feet = (int)fracfeet; inch = 12 * (fracfeet - feet); } }; int main() { Distance d(0, 0); //呼叫二個參數的建立者 float m = 3.5; //m = 3.5 m d = m; //呼叫一個參數的建立者 return 0; //正常結束程式 }
12.3.3 類別型態轉基本型態 • Distance型態的資料轉成float型態 • 範例 const float MTF = 3.280833; class Distance //宣告Distance類別 { int feet; float inch; public: Distance (int f, float in) //Distance類別建立者 { feet = f; inch = in; }
12.3.3 類別型態轉基本型態 (續) • 範例續 operator float() { //多載float型態函數 float fracfeet = inch / 12; fracfeet = float(feet); return fracfeet / MTF; } }; int main() { Distance d(2, 3); //呼叫Distance建立者 float m; //宣告浮點數變數m m = d; //呼叫operator float函數 return 0; //正常結束程式 }
12.3.4 類別型態轉類別型態 • Polar型態的資料轉成Cartesian型態 class Cartesian { //宣告 Cartesian 類別 double x; double y; public: Cartesian () {x = y = 0.0;} }; class Polar { //宣告Polar類別 double radius; double angle; public: Polar(double r, double a) { radius = r; angle = a; }
12.3.4 類別型態轉類別型態 (續) • 範例續 operator Cartesian() { //多載Cartesian函數 double xx, yy; xx = radius * cos(angle); yy = radius * sin(angle); return Cartesian(xx, yy); } }; int main() { Polar p(2.0, 35.0); //建立極座標p點位置 Cartesian c; //建立平面座標c c = p; //呼叫Cartesian函數 return 0; //正常結束程式 }
12.3.4 類別型態轉類別型態 (續) • Polar型態的資料轉成Cartesian型態 • 範例 class Polar //宣告Polar類別 { double radius; double angle; public: Polar(double r, double a) { radius = r; angle = a; } double getr() {return radius;} double geta() {return angle;} };
12.3.4 類別型態轉類別型態 (續) class Cartesian { //宣告Cartesian類別 double x; double y; public: Cartesian() {x = y = 0.0;} Cartesian(double a, double b) {x = a; y = b;} Cartesian operator = (Polar p) { //定義多載 = 號函數 double r = p.getr(); double a = p.geta(); x = r * cos(a); y = r * sin(a); return Cartesian(x, y); } };
12.3.4 類別型態轉類別型態 (續) • 範例 int main() { Polar p(2.0, 35.0); //建立極座標p點位置 Cartesian c; //建立平面座標c c = p; //呼叫多載 = 號函數 return 0; //正常結束程式 }
Exercise • 類別Polar3D • 定義私有資料成員:range, azimuth, elevation • 定義公有成員函數: • 三參數的建構子:設定資料成員初值 • 3個get函數 • 類別Cartesian3D • 定義私有資料成員:x, y, z • 定義公有成員函數: • 無參數建構子:設定資料成員初值 • operator= :將極座標轉換為笛卡兒 座標 • show:印出x, y, z座標值 • 撰寫main函數 • 宣告Polar3D及Cartesian3D的物件變數 • 將Polar3D物件轉換型態為Cartesian3D物件 • 呼叫show函數印出其值