
| 實習目標 | 練習依照 UML 的類別圖實作類別, 製作類別間靜態的連結, 練習撰寫建構元與解構元 |
|---|---|
| 步驟一 |
請參考下面 UML 的類別圖, 製作所需要的類別
這是一個描述類似海洋大學這樣子的組織的課程資訊系統, 主要針對所有開設的課程來描述相關的組織架構, 首先學校裡面有好幾個學院, 每一個學院裡面又有不同的系所, 每一個系所每個學期都會開設許多的課程, 系所也有許多的老師, 每個課程都有一個老師在負責授課。 在這個實習中我們針對紅色的部份來製作, 下一個實習中我們實作整個架構, 也探討這個架構有什麼樣的問題存在 |
| 步驟二 | 請定義 University, College 和 Department 這三個類別, 其中的資料部份先用你覺得最方便的型態, 例如 m_name 可以用 string 類別或是字元陣列 char [] 來實作, 所有類別內的資料成員基本上都是 private 的 |
| 步驟三 | 接下來要建構類別間的關係, 例如我們學校裡有四個學院, 所以在 University 類別中要有一個容器物件,
m_colleges, 你可以用 vector<College> 來製作, 如此在 University 解構時, 所有的 m_colleges
也都會一起解構; 如果考量效率的話, 你也可以用 vector<College *> 來製作, 但是解構就需要自己寫了。
請注意, 如果你選擇使用 vector<College> 來製作, 你會發現 vector<College>::push_back(College) 函式會需要傳入一個 College 物件, 此時會呼叫所謂的拷貝建構元 (copy constructor) 來處理參數的拷貝, 目前我們還沒有談到拷貝建構元的寫法和使用的時機, 所以如果你要使用 vector<College> 來實作的話, 建議你其它所有的關係也都用 vector<Department>, vector<Institute>, vector<Teacher>, vector<Course> 來實作, 如此實作除了效率會造成一些小問題之外, 唯一真正的問題在於雙向的連結 (例如 Course - Teacher 間的連結)。 如果你覺得每個學校的學院變化不大, 不需要用 vector 那麼一般化的容器物件來製作, 你也可以像 3bags 程式那樣子用陣列來實作, 例如 College colleges[4]; 在 C++ 中你也可以選擇用指標陣列來實作, 如此可以省掉許多不必要的資料拷貝的動作, 例如 College *colleges[4]; 只是記得要在初始化 University 物件 時就透過 new 和 delete 來配置和釋放那些 College 物件的記憶體 在 College 中有 Department, 你可以用 vector<Department *> 來定義, 如此在解構 College 時, Department 不會自動被解構, 你可以自行掌握所有物件的生命週期 注意什麼時候用 vector, 什麼時候用 C/C++ 語法裡原本的陣列, 完全是效率和程式碼大小的考量, 你可以斟酌程式的複雜度, 可讀性和效率來使用 |
| 步驟四 |
接下來我們要定義建構元,
建構元主要將每一個資料成員適當地初始化,
資料成員除了狀態變數之外,
也應該包括架構物件間連結的所有資料,
所以上層物件 (例如 University 類別的物件)
的建構元執行完畢之後,
通常整個系統物件的架構都已經架起來了。
(因為它間接地會讓每一個物件的建構元都執行過。)
相對地解構元除了釋放自己類別內使用的記憶體外, 常常也會將整個物件架構摧毀。 有些建構元可以有預設的數值, 有些則需要在建構時將資料當做參數傳遞進去, 我們這個應用程式的資料量有點大, 如果為了兼顧彈性, 也不適合將所有資料物件用預設的方式建立起來, 所以我們打算由檔案串流中讀取資料。 |
| 步驟五 |
我們把資料放在 ntou1.txt 檔案內, 資料如下:
海洋大學 // 學校名稱
5 // 學院個數
生命與資源科學院 // 第一個學院名稱
2 // 此學院內學系個數
食品科學系 // 第一個學系名稱
水產養殖系 // 第二個學系名稱
海運學院 // 第二個學院名稱
3
商船學系
航運管理學系
機械與輪機工程系
理學院 // 第三個學院名稱
1
海洋科學系
工學院 // 第四個學院名稱
4
電機工程學系
資訊工程學系
河海工程學系
系統工程暨造船學系
技術學院 // 第五個學院名稱
3
運輸技術系
輪機工程系
導航與通訊系
此檔案內每一筆資料代表意義以及讀取方法請參考
testRead1.cpp,
以及 testRead1.exe (請下載後執行)
請設計各個建構元函式, 依據此資料檔案內容建構各個物件, 例如: College 類別的建構元如下:
College::College(ifstream &infile)
{
char buf[50];
getline(infile, m_name, '\n'); // string m_name; 學院名稱
int numberOfDepartments;
infile >> numberOfDepartments;
infile.getline(buf, 50, '\n');
int iDept;
for (iDept=0; iDept<numberOfDepartments; iDept++)
m_departments.push_back(new Department(infile));
// vector<Department *> m_departments;
}
請注意, 由於在建構元中產生了這些 Department
物件,
所以在解構元中需要把它們釋放掉,
才不會有記憶體的遺失
College::~College()
{
std::vector<Department *>::iterator iter;
for (iter=m_departments.begin();
iter<m_departments.end();
iter++)
delete *iter;
}
|
| 步驟六 |
為了作基本的測試,
我們在 University, College, 和 Department 類別內都增加一個 print(ostream &)
的公開成員函式,
個自將自己類別的內容印出, 例如:
void University::print(std::ostream &os)
{
os << "學校名稱:" << m_name << std::endl;
std::vector<College *>::iterator iter;
for (iter=m_colleges.begin();
iter<m_colleges.end();
iter++)
(*iter)->print(os);
}
注意 ostream 參數必須使用參考變數或是指標變數,
以避免解構全域串流物件
|
| 步驟七 |
你可以在 University
類別中寫一個 static 的成員函式來測試看看目前所寫的功能:
void University::unitTest()
{
ifstream infile("ntou1.txt");
if (!infile)
std::cout << "Cannot open ntou1.txt!!\n";
else
{
University ntou(infile);
ntou.print(std::cout);
}
}
範例執行程式 campusCourse1.exe (請下載後執行)
|
| 步驟八 | 請助教檢查後, 將所完成的 project (去掉 debug/ 資料匣下的所有內容) 壓縮起來, 選擇 Lab6-2 上傳, 後面的實習課程可能需要使用這裡所完成的程式 |

回
C++ 物件導向程式設計課程
首頁
製作日期: 06/12/2008
by 丁培毅 (Pei-yih Ting)
E-mail: pyting@mail.ntou.edu.tw
TEL: 02 24622192x6615
海洋大學
電機資訊學院
資訊工程系
Lagoon