第十八章 类别与物件.docx
《第十八章 类别与物件.docx》由会员分享,可在线阅读,更多相关《第十八章 类别与物件.docx(16页珍藏版)》请在冰豆网上搜索。
第十八章类别与物件
第十八章類別與物件
18-1程式設計方法的演進
演進一.functionorsubroutine
—使程式變的更有組織,提高程式的再利用率
1.經嚴格測試後,函數被保留下來,成為處理同類問題之buildingblocks
2.同一類函數可以聚集成模組(module)
3.有系統的方式安排各程式模組,搭配嚴謹的輸出輸入資料控管,稱為structuredprogrammingorprocedural-basedprogramming
演進二.物件導向程式設計(Object-OrientedProgramming,OOP),人以「物件導向」的方式來認識世界
1.自然界中萬物皆為具有各種特性(attribute),有各種特殊的行為(behavior),視為一個object
2.物件導向程式設計的精神:
程式中保留各種物件的特性,規劃出使用者與物件,以及物件與物件之間的互動關係
18-2抽象化和資料的隱藏
Abstraction抽象化
考慮三要點(規劃程式用)
(1)系統有哪些物件參與
(2)參與物件特質
(3)物件如何與外界互動
Encapsulation封裝
1.attribute
如蛋黃,隱藏在中心,不能夠直接碰觸,代表了物件的狀態
2.interface
如蛋殼,可以直接與外界接觸
3.behaviors
如蛋白,可以經由介面與外界的互動而改變內部的特徵值,並把反應經由介面表現出來
18-3object與class的關係
任何問題所涉及的物件,與有下列兩種特性
1.狀態(state)2.行為(behavior)對應至軟體為
state←→datamembers
behavior←→memberfunctions
例如:
structMember
{
intAge;
charName[20];
};
故Member之state包括Age及Name(datamember),行為如Inputfile.open(behavior)
18-4基礎class
(參考洪維恩所著之「C++教學手冊」)
1、以struct來建構視窗矩形面積
假設視窗編號id,視窗寬width,高height
1.定義struct
structWIN
{
charid;
intwidth;
intheight;
};
2.定義面積之函數
intarea(WINw)
{
returnw.width*w.height;
}
3.主程式
intmain()
{
WINwin1;
win1.id='A';
win1.width=50;
win1.height=40;
cout<<"Window"<return0;
}
練習1.將上述片斷程式寫成完整程式
討論:
area()函數的width與height屬性是用來計算面積,如果能把三者封裝(encapsulate)在一起,更能表達為一個完整的類別
2、類別
—由「資料成員」與「函數成員」封裝而成
(1)Datamember:
~例如前例之width、height
(2)Functionmember:
~例如前例之area()
(3)Encapsulation:
~把事物的資料與相關函數包在一起,形成特殊結構,如以下圖示
classDatamember
Functionmember
1.Classdecaration
語法:
class類別名稱
{
public:
資料型態變數名稱;//Datamember
...
回傳値型態函數名稱(參數列){//Functionmember
statement;
return;
}
};
Example:
classCWIN
{
public:
//宣告成員屬性為公有
charid;
intwidth;
intheight;
intarea(){
returnwidth*height;//可直接使用成員
}
};
說明:
public:
代表其成員(member),可隨意在class外部作存取
private:
成員只能在類別內部作存取,也可經由public的Functionmember存取private成員
如果省略public,則所有成員均為private
2.建立物件與存取
Example:
CWINwin1;//Declaringavariablewin1belowCWINclass(instance)
win1.id='A';//存取物件成員
win1.width=50;//存取物件成員
win1.height=40;//存取物件成員
範例練習1.將上述過程建立一個完整的程式,並將win1之成員印在螢幕上
範例練習2.查詢上題宣告所建立物件佔了多少bytes可使用sizeof(win1)或sizeof(CWIN)即可得知
3.使用函數(函數已定義於class之內)
語法:
物件名稱.函數名稱(參數列)
Example:
(18-3-2.cpp)
可於範例練習1中加入下列指令
cout<<"Area="<完整程式如下:
#include
usingstd:
:
cout;
usingstd:
:
endl;
usingstd:
:
cin;
classCWIN
{
public:
charid;
intwidth;
intheight;
intarea()
{
returnwidth*height;
}
};
intmain()
{
CWINwin1;
win1.id='a';
win1.width=50;
win1.height=60;
cout<<"Theidofwin1is"<cout<<"Thewidthofwin1is"<cout<<"Theheightofwin1is"<cout<<"Theareaofwin1is"<return0;
}
可將class與mainprogram分開,如下
(1)Area.h
程式碼,檔名area.h
#ifndefarea_h
#definearea_h
classCWIN
{
public:
charid;
intwidth;
intheight;
intarea()
{
returnwidth*height;
}
intperimeter()
{
return2*(width+height);
}
};
#endif
(2)18-1-2.cpp
程式碼
#include
usingstd:
:
cout;
usingstd:
:
endl;
usingstd:
:
cin;
#include"area.h"
intmain()
{
CWINwin1;
win1.id='a';
win1.width=50;
win1.height=60;
cout<<"Theidofwin1is"<cout<<"Thewidthofwin1is"<cout<<"Theheightofwin1is"<cout<<"Theareaofwin1is"<cout<<"Theperimeterofwin1is"<return0;
}
4.於類別內定義多個函數成員
class內可定義多個函數,如下例
classCWIN
{
public:
charid;
intwidth;
intheight;
intarea()
{
returnwidth*height;
}
intperimeter()
{
return2*(width+height);
}
};
範例練習(18-3-3.cpp)
於主程式增加如下程式
cout<<"Perimeter="<5.於類別外定義多個函數成員
Class外定義函數成員時,需在類別的定義內宣告函數的原型(prototype),如下例
classCWIN
{
public:
charid;
intwidth;
intheight;
intarea();//declarationprototype
};
intCWIN:
:
area()//:
:
範疇解析運算子
{
returnwidth*height;
}
範例練習(18-3-4.cpp)將上例加入範例(18-3-3.cpp)
6.thispointer
用途:
強調「物件本身的資料成員」
語法:
classCWIN
{
public:
charid;
intwidth;
intheight;
intarea()
{
returnthis->width*this->height;
}
};
範例練習(18-3-5.cpp)將上述this指標加程式中
7.類別內呼叫函數成員
如下例:
classCWIN
{
public:
charid;
intwidth;
intheight;
intarea(){
returnwidth*height;
}
voidshow_area(void)
{
cout<<"Window"<}
};
範例練習(18-3-6.cpp)於主程式中加入下列敘述
win1.show_area();
18-5函數引數的傳遞與多載
1、引述的傳遞
之前18-4所撰寫的函數均無引述傳遞,如下
intarea(void){
returnwidth*height;
}
其實函數可以加上各種資料型態的引數,如下例
classCWIN
{
public:
charid;
intwidth;
intheight;
intarea()
{
returnwidth*height;
}
voidset_data(chari,intw,inth)
{
id=i;
width=w;
height=h;
}
};
voidshow_area(CWINwin)
{
cout<<"Window"<}
intmain(void)
{
CWINwin1;
win1.set_data('B',50,40);
show_area(win1);
return0;
}
上例中set_data函數為win1之成員
範例練習(18-4-1.cpp),將上述過程寫成程式
2、函數的多載
以下例說明:
(18-4-2.cpp)
classCWIN
{
public:
charid;
intwidth;
intheight;
intarea()
{
returnwidth*height;
}
voidshow_area()
{
cout<<"Window"<}
voidset_data(chari,intw,inth)//FirstFunctionofset_data()
{
id=i;
width=w;
height=h;
}
voidset_data(chari)//SecondFunctionofset_data()
{
id=i;
}
voidset_data(intw,inth)//ThirdFunctionofset_data()
{
width=w;
height=h;
}
};
intmain()
{
CWINwin1,win2;
win1.set_data('A',50,40);
win2.set_data('B');
win2.set_data(80,120);
win1.show_area();
win2.show_area();
return0;
}
說明:
win1.set_data('A',50,40)→win1物件的所有資料成員皆可被設値
win2.set_data('B')→設定id的值
win2.set_data(80,120)→設値width及height
結論:
同一名稱的函數可具有不同的引數輸入
18-6公有成員與私有成員
如果資料成員沒有一個機制來限定類別中成員存取,容易造成錯誤的輸入
完整設定方式如下:
class類別名稱
{
private:
私有成員
...
public:
公有成員
...
};
例如:
id、width與height資料成員為私有,area()函數為公有
classCWIN
{
private:
charid;
intwidth;
intheight;
public:
intarea()
{
returnwidth*height;
}
};
依據上述定義,下列程式為錯誤示範
intmain()
{
WINwin1;
win1.id='A';
win1.width=-5;
win1.height=12;
return0;
}
因此為解決上述問題,需要建立公有成員(publicmember)來解決
如下例:
classCWIN
{
private:
charid;
intwidth;
intheight;
public:
intarea()
{
returnwidth*height;
}
voidshow_area()
{
cout<<"Window"<}
voidset_data(chari,intw,inth)
{
id=i;
if(w>0&&h>0)
{
width=w;
height=h;
}
else
cout<<"inputerror"<}
};
intmain()
{
CWINwin1;
win1.set_data('A',50,40);
win1.show_area();
return0;
}
說明:
1.透過公有成員以存取修改私有成員id、width與height因此可以在公有函數成員內和加上判斷的程式碼
2.把資料成員和函數成員依功能劃分為「私有」與「公有」,然後包裝在一個類別內來保護
18-7友誼函數(friendfunction)
雖然不屬於某一類別之成員的函數,但是能存取此類別私有的成員,如下例
classCWIN
{
public:
voidset_data(chari,intw,inth)
{
id=i;
width=w;
height=h;
}
private:
charid;
intwidth;
intheight;
friendvoidshow_member(CWIN);
};
voidshow_member(CWINw){
cout<<"Window"<cout<<",width"<cout<<",height"<}
intmain()
{
CWINwin1,win2;
win1.set_data('A',50,40);
win2.set_data('B',80,60);
show_member(win1);
show_member(win2);
return0;
}
說明:
藉由友誼函數,使show_member()可以存取類別裡的私有成員(18-6-1.cpp)