Transcript 的類別(Class)
OOP9
類別Class
1
物件導向式問題分析
傳統的程式設計方式-「程序導向」式的設
計方法
「功能」為何?
那些「程序」可以完成這些功能?
物件導向式的設計方法
找出「物件」(Object)
物件就是”東西”
訊息傳遞(Message Passing)
2
物件導向程式語言
物件導向語言(OOP),主要用來描述一個物
件(Object)的類別(Class),以及如何達成
所謂動態繫結(Dynamic Binding) 、同名異
式(Polymorphism)、覆蓋(Override)、覆載
(Overload)、類別的繼承(Inheritance)等
等機制
常見的物件導向程式語言
C++
Java
Smalltalk
ObjectPascal
3
Object
• 類別Class object’s attribute(物件的屬性)
有2個
– Data(資料), property (Java中稱為field)
• 又稱”成員變數”Member variable (或data
variable)
– Method
• 又稱”成員函數” Member function
4
物件導向程式語言
• 物件導向程式語言的優點
– 模組化設計(Module Design)
– 獨立且合作
– 容易維護(Easy to maintain)
– 可重複使用Reuse / Software IC
5
類別Class
本章主題
類別(Class)的宣告
操作成員(Operator Member)的定義與
行內函式(Inline function)
建構元(Constructor)與解構元
(Destructor)
合成使用類別
靜態的類別成員
6
類別的宣告
回顧結構(struct)定義
【結構定義範例】
struct 為保留字
struct Date{
int year;
int month;
int day;
};
Date 為結構的名稱
7
類別的宣告
•
•
•
•
•
class 類別名稱
{
private:
型別 成員資料 ;
public:
傳回值 成員函式1(傳入值……);
傳回值 成員函式2(傳入值……) //成員函式2 為一連線函式。
{
//程式碼
}
};
傳回值 類別名稱::成員函式1(傳入值……)
{
//程式碼
}
類別名稱 變數名稱1;
類別名稱 變數名稱2;
變數名稱1.成員函式1(傳入值……);
8
類別的宣告
【類別定義範例】
class 為保留字
class Date{
Date 為類別的名稱
public:
Date();
void setDate(int, int, int);
操作成員的定義
void printDate(int);
private:
int year;
資料成員的定義
int month;
int day;
};
須以分號結束類別的定義
9
類別的使用
類別變數 - 案例/物件
Date Today, *ptrDate, Holiday[15];
public與private存取等級
不允許直接存取private資料成員
【錯誤的語法】
Today -> year = 2001;
ptrDate.year = 2001;
cout << Holiday[0] -> year;
10
操作成員的定義
• 操作成員的定義: 定義函式的內容
【程式範例】
// 程式名稱: oop_12_2.cpp
// 程式功能: 定義一個 Date 類別,設定其變數值,並將之印出來
//printDate 操作成員,用來印出資料成員的內容
void Date::printDate(int type)
{ //可以直接存取 private 資料成員
if(type==WEST)
cout << MName[month-1]<< " " << day << "," << year;
if(type==EAST)
cout << year<<"/"<< month << "/" << day;
}
//setDate 操作成員,用來改變資料成員的內容
void Date::setDate(int y, int m, int d)
{ //可以直接存取 private 資料成員
year = y;
month = m;
day = d;
}
11
行內函式
• 行內函式: 將操作成員的定義(函式的
內容)寫在類別的定義中
class Date{
public:
Date(){ year=month=day=0 };
void setDate(int y, int m, int d)
{
year=y; month=m; day=d;
};
void printDate(int);
private:
int year;
int month;
int day;
};
12
行內函式
• 行內函式: 將操作成員的定義(函式的
內容)寫在類別的定義之中
class Date{
public:
Date(){ year=month=day=0 };
void setDate(int y, int m, int d)
{
year=y; month=m; day=d;
};
void printDate(int);
private:
int year;
int month;
int day;
};
13
行內函式
• 使用inline保留字將操作成員定義成為
行內函式
inline void Date::printDate(int type)
{ //可以直接存取 private 資料成員
if(type==WEST)
cout << MName[month-1]<< " " << day << "," << year;
if(type==EAST)
cout << year<<"/"<< month << "/" << day;
}
14
建構元(Constructor)
• 建構元是與類別同名稱的成員函式
(member function),主要是用來進行
資料成員的初始值設定(Initial value
setting)
• 一個類別可以定義多個建構元,用以提
供不同的初始化方式
• 建構元是不允許指定函式回傳資料型態
15
建構元(Constructor)
• class 類別名稱
{
private:
型別 成員資料 ;
public:
類別名稱( void ); // 建構子函式1
類別名稱(傳入值……); // 建構子函式2
傳回值 成員函式1(傳入值……);
傳回值 成員函式2(傳入值……) //成員函式2 為一連線函式。
{
//程式碼
}
~類別名稱( ); //解構元函式
};
• 類別名稱 變數名稱1; //會呼叫"建構子函式1"
• 類別名稱 變數名稱2(傳入值……); //會呼叫"建構子函式2"
16
預設引數建構元
• 當呼叫建構元時,若無提供足夠的參
數值,建構元會以預設的引數值做為
初始值
【程式範例】
// 程式名稱: oop_12_3.cpp
// 程式功能: 定義一個 Date 類別,以預設引數建構元初始化資料成員
class Date{
public:
Date(int=0, int=0, int=0); //預設引數建構元
void setDate(int, int, int);
void printDate(int);
private:
int year;
int month;
int day;
};
17
解構元(DeConstructor)
• 解構元的名稱與建構元相同,但名稱
前面須加上 ~ 符號
• 解構元的作用與建構元剛好相反,它
主要用來釋放物件所佔用的記憶體空
間
• 解構元不接受任何參數,也不傳回任
何值
• 一個類別只允許定義一個解構元
18
解構元 – 範例
【程式範例】
// 程式名稱: oop_12_4.cpp
// 程式功能: 說明解構元如何清除資料成員所佔用的記憶體
class GiveMeMemory{
public:
GiveMeMemory();
//建構元
~GiveMeMemory();
//解構元
void printData();
private:
int *memory;
int mind;
};
int main(void)
{
GiveMeMemory M; //呼叫建構元配置記憶體並設定初始值
M.printDate();//印出資料成員內容
return 0; //結束 main()之前,呼叫解構元
}
19
解構元 – 範例
GiveMeMemory::GiveMeMemory()
{
memory = new int[10]; //要求記憶體空間給 memory
for(int i=0; i<10; i++) memory[i]=i+1; //設定 memory 的初始值
mind = 100; //設定 mind 的初始值
}
GiveMeMemory::~GiveMeMemory()
{
delete []memory; //清除 memory 所佔領的記憶體空間
cout << “\nI am out!”;
}
20
合成使用類別
• 在一個類別中使用其他類別作為其資
料成員的一員
【程式範例】
// 程式名稱: oop_12_6.cpp
// 程式功能: 定義一個 MemorialDay 類別,記錄紀念日的日期
#include "oop_DATE_5.h" //引用 Date 類別
#include <iostream.h>
class MemorialDay{
public:
MemorialDay(char *, int, int, int);
void list();
private:
char nameMD[30]; //紀念日名稱
Date memorialDay; //紀念日
};
21
靜態的類別資料成員
• 靜態(Static)資料成員: 所有的類別
案例共用一個資料
【程式範例】
// 程式名稱: oop_12_7.cpp
// 程式功能: 定義一個 MemorialDay 類別,記錄紀念日的日期
#include "oop_DATE_5.h" //引用 Date 類別
#include <iostream.h>
class MemorialDay{
public:
MemorialDay(char *, int, int, int);
~MemorialDay();
void list();
static int numDays(void); //傳回靜態資料值
private:
char nameMD[30]; //紀念日名稱
Date memorialDay; //紀念日
static int NumOfDays; //靜態資料成員
};
22
靜態的類別資料成員
• class 類別名稱
{
private:
型別 成員資料 ;
static 型別 靜態成員資料 ; //只有宣告而
己
public:
傳回值 成員函式1(傳入值……);
};
• 型別 類別名稱::靜態成員資料 ; //定義靜態成
員資料
23
靜態資料成員
//在主程式之前必須初始化靜態資料成員
int MemorialDay::NumOfDays = 0;
int main(void){
//沒有案例時,仍然可以取得靜態資料成員的值
cout << "總共有" << MemorialDay::numDays() << "個紀念日" << endl;
MemorialDay *Day1 = new MemorialDay("端午節", 2002, 6, 15);
MemorialDay MoonFestival("中秋節", 2002, 9, 21);
cout << "總共有" << Day1->numDays() << "個紀念日" << endl;
Day1->list();
MoonFestival.list();
delete Day1;
cout << "總共有" << MoonFestival.numDays() << "個紀念日" << endl;
MoonFestival.~MemorialDay();
cout << "總共有" << MemorialDay::numDays() << "個紀念日" << endl;
}
24
靜態的類別資料
• 靜態類別資料
– 當成員資料為定義成靜態時,每一個物件,都
只有一個共用的靜態資料項。當同類別的全部
物件需要共同的資料訊息時,靜態變數便顯得
特別有用。靜態資料成員變數的特性和一般靜
態變數一樣,雖然僅可在類別中被參考,但生
命週期卻和整個程式相同。
25
CLASS
• class是一個使用者自訂的型態,正式物件導向程式設計的
主要觀念,它們允許你隱藏程式的部分功能,限制部份成員
的外部存取,達到封裝的目的
• 和structure不一樣, 包含資料與函式
• class class_name
{
class_member_declaration_list
};
定義的成員預設為私有的(private)
26
CLASS
• class class_name
{
private:
declaration_list;
public:
declaration_list;
protected:
declaration_list;
};
• class screen
{
private:
int m_nWidth;
int m_nHeight;
int m_x; int m_y;
protected:
~screen();
public:
screen();
//可有多個不同的constructor
void moveto(int, int)
void resize(int, int);
};
27
CLASS
#include “screen.h”
• void screen::resize(int w, int h)
{
m_nWidth=w;
m_nHeight=h;
}
• void screen::move(int x, int y)
{
}
28
CLASS
• screen myScreen; //啟動constructor
• screen bufScreen=myScreen; //拷貝所有資料成員
• screen* ptr= new screen;
myScreen=*ptr;
ptr=&bufScreen;
• screen s(20, 90);
• screen *ps=new screen(20, 90);
• myScreen.moveto(10,20)
ps->moveto(10,20)
29
this 指標
• void screen::resize(int w, int h)
{
this->m_nWidth=w;
this->m_nHeight=h;
}
• screen& screen::xxx()
{
return *this;
}
30
static類別成員
• 有時候同一類別的所有抽象體必須要能存取到同一個共用
的變數
class chatroom
{
private:
static int m_nCount;
}
• Const int m_nT;
31