C++ How to Program 7/E 筆記
第三章 類別與物件簡介
學習目標
|
|
GradeBook 類別的UML類別示意圖
在UML中,妹個類別都會在UML類別示意圖(UML class diagram)中以一個長方形代表,裡面有三個部分。
中間空,的表示GradeBook 類別沒有任何屬性。
第三行「+」表示displayMessage是一種UML公用(public)型的操作。(即C++的public 成員函式)
()是用來建立操作模型。在此範例中displayMessage無需額外資料便可執行工作。
定義一個具有「參數」的成員函式
參數(parameter) 可提供成員函式在執行工作所需要的額外資訊。
就如同汽車需要加速,參數即是在幫助汽車決定加速程度。
呼叫函式時,呼叫者會提供每個參數的「值」——>即引數(Argument)
圖解
此時的GradeBook 類別的UML 類別示意圖
資料成員、set 函式與 get函式
我們將程式的所有辨識都宣告在main函式中,在函式定義主體中宣告的變數,就稱為區域變數(local variable)。區域變數要先宣告,才能在函式中使用。而在這個該函數之外的地方皆無法存取這個變數。(當然有例外)
類別通常由一或多個成員函式組成,這些函式可操控特定物件的屬性。
屬性由類別定義中的變數表示,這種變數稱作資料成員(data member)。資料成員會在類別定義中宣告,但他的宣告在成員函式定義主體的外部。
在下方範例中Gradebook類別將課程名稱當作資料成員,因此可在程式中隨時使用或修改它。
原則上,資料成員應宣告為private,成員函式應宣告為public。
雖然public 和private存取修飾子可以重複交錯,但最好統一羅列。
用存取修飾子private宣告資料成員稱作資料隱藏(data hiding)。當成是建立(實體化)一個 GradeBook 物件時,此物件就封裝(隱藏)了資料成員courseName,只有該類別的成員函式能存取他。
含一個資料成員、一個set 函式與get函式的GradeBook UML類別示意圖
courseName 屬性的UML型別是String,對應到 C++ 的 string。資料成員courseName 在C++中是 private,所以類別示意圖在屬性名稱前面加上減號 (-)。
- setCourseName 操作有一個String型別的參數,叫做name。
- getCourseName在C++中的傳回型別是String,因此在()之後以「:string」表示。
- setCourseName、displayMessage不會傳回任何值(傳回void),故()後方為空。
以建構子將物件初始化
在前面的範例中,建立GradeBook 物件時,資料成員courseName 會預設初始化為空字串。若在建立時,想同時提供課程名稱呢?
⇒⇒所宣告的每個類別都可提供建構子(constructor)
*建構子是一種特殊的成員函式,名稱必須和類別相同,編譯器才能區別他與其他成員函式。建構子與其他成員函式的一個重要差異,就是建構子不能還回數值,因此他不能指定傳回型別(就連void也不行)。通常,建構子都宣告為public。
C++建立每個物件都要呼叫建構子,以確保程式使用物件前,每個物件均已初始化。建立物件時,就隱含了建構子的呼叫。
若類別沒有明確寫出建構子,編譯器就提供一個預設建構子(default constructor),也就是沒有參數的建構子。
*為類別提供預設建構子的兩種方式
沒有參數的建構子就叫預設建構子。預設建構子的建立方式有兩種:
- 若類別沒有定義建構子,編譯器就會自行為他建立一個預設建構子。為初始化的變數通常會包含一個「垃圾值」(garbage value)
- 由你明確定義一個沒有參數的建構子。這種預設建構子可執行你指定的初始化動作,若資料成員本身是類別物件,也會呼叫每個資料成員的預設建構子。
將建構子納入GradeBook 類別的UML類別示意圖
在此GradeBook 類別模型,他有一個建構子,其參數名稱是name,型別是string。
為了區分建構子和類別操作,UML在建構子名稱前面會加上
<<contructor>>。習慣上會將建構子放在其他操作前面。
✯✯✯ 將類別放在獨立檔案以提高重複使用性
建立類別定義的好處在於,若套件設定得當,程式設計者便可重複使用我們的類別。但是若有其他程序員想要使用GradeBook類別,得注意到不能全部照抄,否則會因為有兩個main韓式,而讓程序錯誤。
在Microsoft Visual C++編譯會產生以下錯誤:
error C2084: fucntion ‘int main(void)’ already has a body
而在GNU C++編譯器會產生如下錯誤
redefinition of ‘int main()’
標頭檔
前面的程式皆為副檔名 (.cpp),此檔稱作原始碼檔案(source-code file)包含GradeBook 類別定義和一個main函式。
在建構物件導向C++程式時,通常會將可再利用的原始碼定義在副檔名為(.h)的檔案中,這就是標頭檔(header file)。程式使用#include箝制處理指令已函入標頭檔,藉此運用可再利用的軟體元件。
如何找到標頭檔
GradeBook.cpp檔案中,第四行檔名是以雙引號 (“ ”)包覆而非(< >)。程式原始碼檔案與使用者自定標頭檔通常會放在相同目錄下,當前置處理器碰到雙引號的標頭檔名時,會再與# include指令出現的檔案相同目錄中尋找標頭檔。若遇到的是<>的標頭檔時,會假設該逼頭飾C++標準函式庫的一部份,而不會尋找被前置處理的程式所在目錄。
將介面與實作分開
軟體工程基本守則——將介面與實作分開(separating interface from implementation)
類別介面(interface of a class)說明類別提供了「什麼」服務給用戶端以及如何要求這些服務,但沒有說明「如何」實作這些服務。類別介面由類別的public 成員函式組成。
注意,每個函式標頭的成員函式名稱前面堆有類別名稱和::,這叫做二元使用域解析運算子(binary scope resolution operator)。他們會把每個成員函式綁到宣告成員函式與資料成員的GradeBook 類別定義上面
若不在函式前面加上「GradeBook :: 」,則編譯器就不知道這些函式是GradeBook 類別的成員函式,會把他們當成全域函式。(page3-31)
注意,每個函式標頭的成員函式名稱前面堆有類別名稱和::,這叫做二元使用域解析運算子(binary scope resolution operator)。他們會把每個成員函式綁到宣告成員函式與資料成員的GradeBook 類別定義上面
若不在函式前面加上「GradeBook :: 」,則編譯器就不知道這些函式是GradeBook 類別的成員函式,會把他們當成全域函式。(page3-31)
在程式裡,我們習慣將類別定義與使用該類別的用戶端程式碼分開,而為了不要讓類別定義中的成員函式實作被修改,進而影響到用戶端程式碼的失靈,因此在編寫程式時,會將類別定義在被分割成成:類別介面和類別實作。此時類別實作會被隱藏起來僅留下類別介面。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// GradeBook.cpp | |
// GradeBook member-fuction definitions.This file contains | |
// implementations of the member functions prototyped in GradeBook.h | |
#include <iostream> | |
#include "GradeBook.h" // include definition of class GradeBook | |
using namespace std; | |
// constructor initializes courseName with string supplied as argument | |
GradeBook::GradeBook (string name) | |
{ | |
setCourseName( name ); // call set function to initialize courseName | |
} // end GradeBook constructor | |
// function to set the course name | |
void GradeBook::setCourseName( string name ) | |
{ | |
courseName = name; //store the course name in the object | |
} // end function setCourseName | |
//function to get the course naeme | |
string GradeBook::getCourseName() | |
{ | |
return courseName; // return object's courseName | |
} // end function getCourseName | |
//display a welcome message to the GradeBook user | |
void GradeBook::displayMessage() | |
{ | |
//call getCourseName to get the courseName | |
cout << "Welcome to the grade book for\n" << getCourseName() | |
<< "!" << endl; | |
} // end function displayMessage |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// GradeBook.h | |
// GradeBook class definition. This file presents GradeBook's public | |
// interface without revealing the implementations of GradeBook's member | |
// functions, which are defined in GradeBook.cpp | |
#include <string > // class GradeBook uses C++ standard string class | |
using namespace std; | |
//GradeBook class definition | |
class Gradebook | |
{ | |
public: | |
GradeBook (string ); // constructor that initializes courseName | |
void setCourseName ( string ); // function that sets the course name | |
string getCourseName(); // function that get the course name | |
void displayMessage(); // fuction that displays a welcome message | |
private: | |
string couseName; // course name for this GradeBook | |
};// end class GradeBook | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// user.cpp | |
// GradeBook class demonstration after separating | |
//its interface from its implementation. | |
#include <iostream> | |
#include "GradeBook.h" // include definition of class GradeBook | |
using namespace std; | |
//fucntion main begins program execution | |
int main() | |
{ | |
//create two GradeBook objects | |
GradeBook gradeBook1( "CS101 Introduction to C++ Programming"); | |
GradeBook gradeBook2( "CS102 Data Strutures in C++"); | |
//display initial value of courseName for each GradeBook | |
cout << "gradeBook1 created for course: " << gradeBook1.getCourseName() | |
<< " \ngradeBook2 created for course: " << grdeBook2.getCourseName() | |
<< endl; | |
} //end main |
jjj
附錄:語法
GradeBook with “Welcome to the Grade Book!”
//
//Define class Gradebook with a member function displayMessage.
// create a GradeBook object, and call its displayMessage function.
#inclued <iostream>
using namespace std;
// GradeBook calss definition
class GradeBook
{
public:
//function that displays a welcome message to the GradeBook user
void displayMessage()
{
cout << " Welcome to the Grade Book!" << endl;
} //end function displayMessage
};// end class Gradebook
//function main begins program execution
int main()
{
GradeBook myGradeBook; // create a GradeBook object named myGradeBook
myGradeBook.displayMessage(); // call objet's displayMessage function
}
|
GradeBook add “couseName”
//
// Define class GradeBook with a member function that takes a parameter;
// Create a GradeBook object and call its displayMessage function.
# include <iostream>
# include <string> // program uses C++ standard string class
using namespace std;
// GradeBook calss definition
class GradeBook
{
public:
// function that displays a welcome message to the GradeBook user
void displayMessage (string courseName)
{
cout << "Welcome to the grade book for\n" << courseName << "!"
<< endl;
} // end function displayMessage
}; // end class GradeBook
//function main begins program execution
int main()
{
string nameOfCourse; // string of characters to store the course name
GradeBook myGradeBook; // create a GradeBook object named myGradeBook
// prompt for and input course name
cout << "Please enter the course name:" << endl;
getline( cin, nameOfCourse ); // read a course name with blanks
cout << endl; // out put a blank line
// call myGradeBook's displayMessage function
// and pass nameOfCourse as an argument
myGradeBook.displayMessage( nameOfCourse );
} // end main
|
資料成員、set、get
//
// define class GradeBook that contains a courseName data member
// and member functions to set and get its value;
// Create and manipulate a GradeBook object with these functions.
# include <iostream>
# include <string>
using namespace std;
//GradeBook class definition
class GradeBook
{
public:
// function that sets the course name
void setCourseName (string name)
{
courseName =name;//store the course name in the project
} // end function setCourseName
// function that gets the course name
string getCourseName()
{
return courseName; // return the object's courseName
}// end function getCourseName
// fucntion that displays a welcome message
void displayMessage()
{
// this statement callls getCourseName to get the
// name of the course this GradeBook represents
cout << "Welcome to the grade book for \n" << getCourseName() << "!"
<< endl;
}// end function displayMessage
private:
string courseName; // course name for this GradeBook
}; // end class GradeBook
// function main begins program execution
int main()
{
string nameOfCourse; // string of characters to store the course name
GradeBook myGradeBook; // create a GradeBook object named myGradeBook
//display initial value of courseName
cout << "Initial course name is:" << myGradeBook.getCourseName()
<< endl;
//prompt for, input and set course name
cout << "\n Please enter the course name:" << endl;
getline(cin, nameOfCourse); // read a course name with blanks
myGradeBook.setCourseName(nameOfCourse); // set the couse name
cout << endl;// outputs a blank line
myGradeBook.displayMessage();// display message with new course name
}//end main
|
定義建構子
//
// Instantiating multiple objects of the GradeBook class and using
// the GradBook constructor to specify the course name
// when each GradeBook object is created.
#include <iostream>
#include <string> //program uses C++ standard string class
using namespace std;
// GradeBook class definition
class GradeBook
{
public:
// constructor initializes courseName with string supplied as argument
GradeBook ( string name )
{
setCourseName( name ); //call set function to initialize courseName
}// end GradeBook constructor
//function to st the course name
void setCourseName( string name )
{
courseName = name; // stroe the coure name in the object
} // end function setCourseName
//fucntion to get the coursename
string getCourseName()
{
return courseName; // return object's courseName
} //end fucntion getCourseName
//display a welcomemessage to the GradeBook user
void displayMessage()
{
//call getCourseName to get the courseName
cout << "Welcome to the grade book for\n" << getCourseName()
<< "!" << endl;
} //end function displayMessage
private:
string courseName; // course name for this GradeBook
}; //end class GradeBook
//function main begins program execution
int main()
{
//create two GradeBook objects
GradeBook gradeBook1("CS101 introduction to C++ Programming");
GradeBook gradeBook2("CS102 Data Structures in C++");
//display initial value of courseName for each GradeBook
cout << "gradeBook1 created for course:" << gradeBook1.getCourseName()
<< "\ngradeBook2 created for course:" << gradeBook2.getCourseName()
<< endl;
} // end main
|
資料參考:
http://pydoing.blogspot.tw/2012/10/cpp-interface-and-implementation.html
留言
張貼留言