第11章 C語言到C++語言 11-1 物件導向程式設計 11-2 青出於藍的C++ 11-3 C++的函數特殊功能 11-4 認識類別 11-1 物件導向程式設計 11-2 青出於藍的C++ 11-3 C++的函數特殊功能 11-4 認識類別 11-5 建構子與解構子 11-6 本章綜合練習
11-1 物件導向程式設計 「物件導向程式設計」 (Object-Oriented Programming, OOP)模式是近年來相當流行的一種新興程式設計理念。 主要讓我們在設計程式時,能以一種更生活化的設計觀念來進行,並且所開發出來的程式也較容易擴充、修改及維護,像是Smalltalk、C++、Java等語言。
物件導向設計相關元件表 物件導向元件 特 色 與 說 明 物 件 物件是一個存在的個體,在VB視窗軟體中,物件可以 是一個圖形、文字檔案等。 類 別 同一類物件的集合體就是類別。類別好比是一個設計 圖,它定義了這類物件的集合體應有的屬性或功能, 而物件就是依據這份藍圖所產生的實體。也就是說, 定義好類別後,可以實作許多物件實體。 屬 性 屬性就是指類別所擁有的靜態特性。 方 法 屬性就是指類別所具有的功能。 事 件 物件該於何時啟動什麼樣的工作,必須由事件來觸 發。例如當在某區域「按下滑鼠左鍵」時,就會產生 「按下滑鼠左鍵」的事件,而視窗軟體本身也會依物 件的功能進行該事件的處理。
物件導向程式設計的三種特性圖
封裝 將屬性(attributes)與行為(behavior)包入一個物件的過程,稱為「封裝」(encapsulation)。 也就是說,「封裝」的作用是將物件的功能細節加以隱藏,而只顯示出所提供的功能介面。
繼承 「繼承」是接近現實生活中的遺傳,例如你的父母生下你,那麼你一定會遺傳到父母的某些特徵,當物件導向技術以這種生活實例去定義其功能時,則稱為「繼承」。 在繼承關係中,被繼承者稱為「基礎類別」或「父類別」,而繼承者則稱「衍生類別」或「子類別」。 而繼承允許我們去定義一個新的類別來繼承既存類別,進而使用或修改繼承而來的方法,並可在子類別中加入新的資料成員與函數成員。
遺傳關係 繼承關係中,一個類別有單一個父類別,稱為「單一繼承」(single inheritance)。如果一個類別有多個父類別,則稱為「多重繼承」(multiple inheritance)。
多形 「多形」也是物件導向設計的重要特性,它展現了動態繫結(dynamic binding)的功能,也稱為「同名異式」(polymorphism)。 「多形」功能可讓軟體在發展和維謢時,達到充份的延伸性。
青出於藍的C++ C++語言可以說是包含了整個C語言,所以C語言的程式在編譯器上可以直接將副檔名c改為cpp,即可編譯成C++語言程式。
表頭檔 舊型標頭檔 說明 新型標頭檔 說明 <math.h> 包含數學運算函數 <stdio.h> 包含標準輸出入函數 <string.h> 包含字串處理函數 <time.h> 包含時間、日期的處 理函數 <iostream.h> <fstream.h> 包含檔案輸出入的處 新型標頭檔 說明 <cmath> <math.h>的新型標頭檔 <cstdio> <stdio.h>的新型標頭檔 <cstring> <string.h>的新型標頭檔 <ctime> <time.h>的新型標頭檔 <iostream> <iostream.h>的新型標頭檔 <fstream> <fstream.h>的新型標頭檔 <exception> 包含例外處理的類別 <string> 包含標準函數庫(std)中String 類別的定義及處理函數
註解 在C語言中的註解(comment)是以/*…*/來表示,而C++除了支援C的註解寫法外,還多了一個雙斜線「//」的單行註解方式,也就是在程式中加入//,//後方所有的敘述都會被視為註解,並沒有註解結束符號。 在C++語言中大都以/*…*/作為多行的註解方式,而以//作為短註解。
名稱空間 名稱空間(namespace),主要是用來區別每個類別庫中的類別名稱,由於各個不同廠商所研發出的類別庫,可能會有相同的類別名稱,所以標準C++語言新增了名稱空間的概念,以用來區別各種定義名稱。 這樣的作法會將所定義的名稱區域化,也就是只有在該名稱空間的區域才能看到或使用定義的名稱,並將所有的程式庫都封裝在std名稱空間中,避免被其他引用的程式庫影響。
名稱空間示意圖
bool資料型態 語法如下: bool 變數; 或是 bool 變數=true (or false); 由於C++包容了C語言的語法,所以C中的關係和邏輯運算子產生的運算式結果,不論是整數型態的運算式或是bool型態運算式,在C++裡都會自動轉換成所需的資料型態。
資料型態轉換 C++言的資料型態轉換,包含了C的自動資料型態轉換和強制資料型態轉換,其規則和方式都與C相同。不過C++的強制資料型態則提供了另外一種新的格式: 舊式C語言的強制資料型態轉換: int a; double d; d=(double)a; C++語言的資料型態轉換: d=double (a);
標準輸出入函數 C++的標準輸出入函數與C中的標準輸出入函數相比,可說是非常簡化與方便。 其中C++的標準輸出指令為cout,讀作c-out,當要輸出資料時,須搭配<<運算子(output operator),表示將指定變數的資料或字串移動至輸出設備。語法格式如下: 字串輸出方式:cout<<"字串"; 數值輸出方式:cout<<變數名稱;
第一個C++程式範例實作:CH11_1 程式範例是第一個C++程式,可輸入兩個數字,並判斷其大小,用意是能讓各位熟悉C的基本架構。
字串 ANSI/ISO C++語言裡的字串函數是由<string>表頭檔所定義,而原本C的字串則被另一個新式表頭檔<cstring>含括,所以C++中是存在兩個字串類別。 一般C版本的字串,是由char字元加上陣列的概念組成,並以’\0’作為結束,如果在C++中要編譯或使用C版本的字串,只需要引用<cstring>表頭檔即可。
字串結合的運算子總表 運算子 功能 用法 = 字串指定 str="字串"; + 字串串接 str1+str2; += 字串串接並指定 == 等於 str1==str2;比較兩個字串是否相等。 != 不等於 str1!=str2;比較兩個字串是否不等。 < 小於 依照ASCII碼的代碼數字比較。 <= 小於等於 > 大於 >= 大於等於 [] 註標 用於字串的陣列。 << 輸出 用於字串的輸出。 >> 輸入 用於字串的輸入。
C與C++字串的宣告與使用範例:CH11_2 程式範例是介紹C與C++字串的各種宣告範例,及示範字串的串接運算作法。
動態配置功能 C++語言中的動態配置的運算子為new和delete,分別取代C中應用於動態配置的malloc()函數和free()函數。
new 宣告方法如下: 資料型態 *指標名稱=new 資料型態(初始值); 1.new運算子會向系統要求配置記憶體,如果配置成功則傳回該記憶體位址,如配置失敗則傳回NULL值。 2.使用new運算子動態配置記憶體時,可同時指定其初始值。
delete delete運算子是取代了C中free()函數的功能。 因為使用new運算子配置的記憶體空間,將會保留到程式結束執行,才會歸還給系統。 因此當配置的記憶體已不再使用時,就要使用delete運算子來釋放該記憶體空間。
new與delete運算子的宣告與使用範例:CH11_3
C++的函數特殊功能 在ANSI/ISO C++的函數部分,貼心地增加了一些功能或應用,來取代一些C中較沒有效率的方法,讓C++在使用上更為方便。
函數的參數預設值 宣告方式與注意事項如下: 以下是四點注意事項: 資料型態 函數名稱(資料型態 參數=數值…); 或 資料型態 函數名稱(資料型態 參數=數值..) { 程式敘述區塊; } 以下是四點注意事項: 參數預設值必須是常數或是全域變數。 參數預設值只能在函數原形或是函數定義中,擇一做設定,不可重覆。 所有參數列中的參數都可指定預設值。 在宣告有多個參數的函數時,不指定預設值的參數必須從參數列的左邊開始放置,然後才是有預設值的參數。如果在呼叫函數時,仍有傳遞參數值的動作,優先於參數預設值。
參數預設值的宣告與使用範例:CH11_4 程式範例示範參數預設值與一般參數值間的差異與優先次序。
傳參考呼叫 傳參考呼叫也是屬於傳址呼叫的一種,但是在傳參考方式函數中,形式參數並不會另外再配置記憶體存放實際參數傳入的位址,而是直接把形式參數作為實際參數的一個別名(alias)。
傳參考呼叫函數的宣告與使用範例:CH11_5 程式範例是以傳參考方式來撰寫Int_swap()函數,並將傳入的整數值進行交換。 在Int_swap()函數定義內的形式參數N_1與N_2,即為實際參數Num_1與Num_2的別名,兩者都參考到相同的變數。
行內函數 C++的行內函數(inline function)類似C語言的參數巨集。 當程式中使用到inline定義的函數時,C++會將呼叫inlie函數的部份,直接替換成inline函數內的程式碼,而不會有實際的函數呼叫過程。
inline函數的宣告與使用範例:CH11_6
函數多載 函數多載(Function Overloading) 是C++新增的功能,藉由函數多載的特性,使得同一個函數名稱可以用來定義成多個函數主體,而在程式中呼叫該函數名稱時,C++將會根據傳遞的形式參數個數與資料型態來決定實際呼叫的函數。 函數多載方式還必須依照以下兩個原則: 函數名稱必須相同。 各多載函數間的參數串列(arguments list)型態不能完全相同。
函數多載的宣告與使用範例:CH11_7 程式範例將利用函數多載觀念來來設計一個簡單回傳所輸入不同型態值的相同名稱函數。
認識類別 在日常生活中,舉目所見皆可當成是一種物件(objects),物件(object)是物件導向程式設計中的基本元素,而每一個物件的建立都必須透過類別(class)的宣告。 C++與C語言最大的差異在於C++加入了類別語法,也因此讓C++成為具有物件導向程式設計的功能。
類別宣告 類別在C++的物件導向程式設計中,是屬於使用者定義的抽象資料型態(Abstract Data Type:ADT),內部中包含此類別資料結構的定義與處理此資料結構的程式碼。 在類別中可以定義多種資料型態,這些資料稱為類別的「資料成員」(Data Member),而類別中存取資料的函數,稱為「成員函數」(Member Function),也可以稱為「方法」(method)。
類別名稱 存取層級關鍵字可分為以下三種: class 類別名稱 { private: // 不被外界所存取,皆未定義時預設值 私有成員 protected: // 只被繼承的類別所引用 保護成員 public: // 無存取現制,可任意存取 公用成員 };
資料成員與成員函數 資料成員 成員函數 「資料成員」就是資料變數的部分,主要作為類別描述狀態之用,各位可以使用任何資料型態在類別內定義。 「成員函數」指作用於資料成員的相關函數,是作為類別所描述之物件行為。通常運用於內部狀態改變的操作,或是與其他物件溝通的橋樑。
建立類別物件 當類別宣告與定義後,等於是建立了一個新的資料形態,然後就可以利用這種形態來宣告和建立物件。建立類別中物件的宣告格式如下: 類別名稱 物件名稱; 類別名稱是指class定義的名稱,物件名稱則是用來存放這一個類別形態的變數名稱。
類別物件的宣告與使用範例:CH11_8 程式範例將利用類別型態所宣告的物件來讓使用者輸入學號、數學成績以及英文成績之後,將總分及平均顯示出來。
建構子與解構子 如果在宣告物件後,希望能指定物件中資料成員的初始值,可以使用建構子(constructor)來宣告。 而解構子(destructor)則是用來釋放物件所佔用之記憶體,以作為其它物件所用。
建構子簡介 建構子(constructor)是一種初始化類別物件的成員函數,可用於將物件內部的私有資料成員設定初始值。 1.建構子的名稱必須與類別名稱相同,例如class名稱為 MyClass,則建構子為MyClass()。 2.不需指定傳回型態,也就是沒有傳回值。 3.當物件被建立時將自動產生預設建構子,預設建構子並不提供參數列傳入。 4.建構子可以有多載功能,也就是一個類別內可以存在多個相同名稱,但參數列不同的建構子。
建構子的宣告與使用範例:CH11_9 程式範例是說明建構子的宣告與定義,並在類別中建立建構子,再於建立類別物件時,給予物件不同的初值。
建構子多載功能的宣告與應用範例:CH11_10 程式範例中將以指標型態來動態配置類別物件,來實作與示範建構子多載功能。
解構子 宣告語法如下: 解構子不可以多載(overload),一個類別只能有一個解構子。 ~類別名稱() { //程式主體 } 解構子不可以多載(overload),一個類別只能有一個解構子。 解構子的第一個字必須是~,其餘則與該類別的名稱相同。 解構子不含任何參數也不能回傳值。 在程式區塊結束前,所有在區塊中曾經宣告的物件,都會依照先建構者後解構的順序執行(first-construct-last-destructor)。
解構子的宣告與使用範例:CH11_11
函數物件傳遞 函數中傳遞物件參數和傳遞一般參數的方式大同小異,只要將一般資料型態參數列改為類別名稱即可。
函數物件傳遞的宣告與使用範例:CH11_12 程式範例定義了square類別,並可透過建構子初始化資料成員。
this指標 this指標為指向物件本身的指標,這個指標是指向記憶體中儲存該物件的位址。
this指標的宣告與使用範例:CH11_13 程式範例是修改CH11_12的程式碼來顯示this指標的宣告與使用方式,並說明當函數回傳值為類別物件時的作法。
範圍解析運算子 有時為了程式可讀性,類別中成員函數的主體程式碼不一定要定義在類別內。 您也可以在類別內事先宣告成員函數的原型,然後在類別外面再來實作成員函數的主體程式內容。
範圍解析運算子:CH11_14 程式範例將示範利用範圍解析運算子在類別外面實作成員函數的程式碼。
求最大公因數程式實作:CH11_15 我們知道使用輾轉相除法,可以求出兩數間的最大公因數。 程式中使用while敘述開始進行輾轉相除的動作,直到相除的餘數等於0(即整數變數Num_2),則離開while迴圈。
朋友函數 封裝最大的特色就是類別內部私有的資料只能由本身的成員函數存取,如果想要讓類別以外的函數也能存取該類別私有資料時,就可以將函數宣告為此類別的「朋友函數」(friend function)。
朋友函數的宣告與實作:CH11_16 程式範例中,Student類別的朋友函數add_score是一個全域函數,宣告完成後,即可存取該類別的私有資料。