跳到主要內容

第三章 類別與物件簡介

C++  How to Program 7/E 筆記
第三章 類別與物件簡介
學習目標
  • 如何定義類別,並使用類別建立物件
  • 如何在類別中定義成員函式,以實作類別的行為
  • 如何在類別中宣告資料成員,以實作類別的屬性
  • 如何呼叫物件的成員函式執行其工作
  • 類別資料成員與函式區域變數的差異
  • 建立物件時,如何使用建構子確保物件資料的初始化
  • 如何建構類別,已將其介面與實作分開,提高再利用



螢幕快照 2016-05-18 下午6.59.17.png


名詞解釋.png


GradeBook 類別的UML類別示意圖

在UML中,妹個類別都會在UML類別示意圖(UML class diagram)中以一個長方形代表,裡面有三個部分。




中間空,的表示GradeBook 類別沒有任何屬性。
第三行「+」表示displayMessage是一種UML公用(public)型的操作。(即C++的public 成員函式)
()是用來建立操作模型。在此範例中displayMessage無需額外資料便可執行工作。


定義一個具有「參數」的成員函式

參數(parameter) 可提供成員函式在執行工作所需要的額外資訊。
就如同汽車需要加速,參數即是在幫助汽車決定加速程度。
呼叫函式時,呼叫者會提供每個參數的「值」——>即引數(Argument)


圖解
類比.png


詳解.png


此時的GradeBook 類別的UML 類別示意圖




資料成員、set 函式與 get函式



我們將程式的所有辨識都宣告在main函式中,在函式定義主體中宣告的變數,就稱為區域變數(local variable)。區域變數要先宣告,才能在函式中使用。而在這個該函數之外的地方皆無法存取這個變數。(當然有例外)


類別通常由一或多個成員函式組成,這些函式可操控特定物件的屬性。
屬性由類別定義中的變數表示,這種變數稱作資料成員(data member)。資料成員會在類別定義中宣告,但他的宣告在成員函式定義主體的外部


在下方範例中Gradebook類別將課程名稱當作資料成員,因此可在程式中隨時使用或修改它。


什麼是資料成員.jpg
原則上,資料成員應宣告為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),也就是沒有參數的建構子


建構子 .png


*為類別提供預設建構子的兩種方式
沒有參數的建構子就叫預設建構子。預設建構子的建立方式有兩種:
  1. 若類別沒有定義建構子,編譯器就會自行為他建立一個預設建構子。為初始化的變數通常會包含一個「垃圾值」(garbage value)
  2. 由你明確定義一個沒有參數的建構子。這種預設建構子可執行你指定的初始化動作,若資料成員本身是類別物件,也會呼叫每個資料成員的預設建構子。


將建構子納入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)






在程式裡,我們習慣將類別定義與使用該類別的用戶端程式碼分開,而為了不要讓類別定義中的成員函式實作被修改,進而影響到用戶端程式碼的失靈,因此在編寫程式時,會將類別定義在被分割成成:類別介面和類別實作。此時類別實作會被隱藏起來僅留下類別介面。

圖解
mmm

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

留言

這個網誌中的熱門文章

【Quora 翻譯&整理】對於程式初學者嘗試解決問題的好網站推薦

原文出處: What are some suggested websites to solve programming problems for beginners? (2016/5/15) 此篇文章強調的是去參加project的那種網站推薦

第一章 電腦、網際網路與全球資訊網簡介

C++  How to Program 7/E 筆記 第一章 電腦、網際網路與全球資訊網簡介 學習目標 基本軟硬體觀念 物件技術觀念(類別、物件、屬性、行為、封裝、繼承) 程式語言的種類 典型的C++開發環境 業界標準物件導向素模語言——UML 沿革 網際網路、球球資訊網與Web 2.0現象的沿革 在Linux 的GNU C++ 與在Microsoft Visual C++環境中測試C++ 應用程式 *結構化程式設計(structured programming) *物件導向程式設計

【Android Development for Beginners】Lesson 2A : Update a Variable in the App

This Notes is according to the udacity free course : Android Development for Beginners The Notes below are my own notes in class. Lesson 2A :  Update a Variable in the App When you put new variable in the MainActivity.java you will get a new results when you press the button"+"