類別的組合
- C++ 支援將現有類別的物件作為新類別的成員,這種方式稱為類別組合。
- 類別組合允許我們以模組化的方式來構建複雜系統,類似於製造業中的組裝生產模式。
例 4_4:類別的組合,線段(Line)類別
- 這個範例展示了一個簡單的
Point
類別,其中包含一個默認建構子和一個複製建構子。
#include <iostream> #include <cmath> using namespace std; class Point { // Point 類別定義 public: Point(int xx = 0, int yy = 0) { x = xx; y = yy; } Point(Point &p); // 複製建構子 int getX() { return x; } int getY() { return y; } private: int x, y; };
- 複製建構子的實現,這裡的複製建構子用來複製
Point
物件的資料成員。
Point::Point(Point &p) { // 複製建構子的實現 x = p.x; y = p.y; cout << "Calling the copy constructor of Point" << endl; }
- 組合類別的定義,
Line
類別包含了兩個Point
類別的物件成員p1
和p2
,以及一個表示線段長度的len
成員。
class Line { // Line 類別定義 public: Line(Point xp1, Point xp2); // 建構子 Line(Line &l); // 複製建構子 double getLen() { return len; } private: Point p1, p2; // Point 類別的物件成員 double len; };
- 組合類別的建構子
Line::Line(Point xp1, Point xp2) : p1(xp1), p2(xp2) { cout << "Calling constructor of Line" << endl; double x = static_cast<double>(p1.getX() - p2.getX()); double y = static_cast<double>(p1.getY() - p2.getY()); len = sqrt(x * x + y * y); }
- 這個建構子初始化了
Line
類別的p1
和p2
成員,並計算了線段的長度。
Line::Line(Line &l) : p1(l.p1), p2(l.p2) { // 組合類別的複製建構子 cout << "Calling the copy constructor of Line" << endl; len = l.len; }
- 這裡展示了
Line
類別的複製建構子,用來複製另一個Line
物件的資料。 - 主函數
int main() { Point myp1(1, 1), myp2(4, 5); // 建立 Point 類別的物件 Line line(myp1, myp2); // 建立 Line 類別的物件 Line line2(line); // 利用複製建構子建立一個新物件 cout << "The length of the line is: " << line.getLen() << endl; cout << "The length of the line2 is: " << line2.getLen() << endl; return 0; }
-
- 執行結果如下:
Calling the copy constructor of Point Calling the copy constructor of Point Calling the copy constructor of Point Calling the copy constructor of Point Calling constructor of Line Calling the copy constructor of Point Calling the copy constructor of Point Calling the copy constructor of Line The length of the line is: 5 The length of the line2 is: 5
組合的概念
- 在類別中的成員可以是另一個類別的物件。這樣的組合可以在已有的抽象基礎上實現更複雜的抽象。
類別組合的建構子設計
- 原則:
- 不僅要負責對本類別中的基本型別成員進行初始化,也要對物件成員進行初始化。
- 宣告形式:
類名::類名(物件成員所需的參數,本類成員參數) : 物件1(參數),物件2(參數),...... { // 函數體的其他語句 }
構造組合類別物件時的初始化順序
- 首先會對建構子初始化列表中列出的成員(包括基本型別成員和物件成員)進行初始化,初始化順序依照成員在類別中定義的順序。
- 成員物件的建構子調用順序會依照物件成員的宣告順序來進行,先宣告的成員會先進行構造。
- 初始化列表中未出現的成員物件,會透過預設建構子(即無參數的建構子)來進行初始化。
- 處理完初始化列表之後,才會執行建構子的主體部分。