21
13 13 第第 第第第第第第第第第 第第 第第第第第第第第第 13-1 13-1 第第第第第第第 第第第第第第第 13-2 13-2 第第第第第第第第第 第第第第第第第第第 13-3 13-3 第第第第第第第第第 第第第第第第第第第 13-4 13-4 第第第第 第第第第

第 13 章 常數、靜態成員與朋友關 係 13-1 常數物件與成員 13-1 常數物件與成員 13-2 物件成員與巢狀類別 13-2 物件成員與巢狀類別 13-3 靜態成員資料與函數

  • View
    241

  • Download
    1

Embed Size (px)

Citation preview

Page 1: 第 13 章 常數、靜態成員與朋友關 係 13-1 常數物件與成員 13-1 常數物件與成員 13-2 物件成員與巢狀類別 13-2 物件成員與巢狀類別 13-3 靜態成員資料與函數

第第 1313 章 章 常數、靜態成員與朋友常數、靜態成員與朋友關係關係

13-1 13-1 常數物件與成員常數物件與成員 13-2 13-2 物件成員與巢狀類別物件成員與巢狀類別 13-3 13-3 靜態成員資料與函數靜態成員資料與函數 13-4 13-4 朋友關係朋友關係

Page 2: 第 13 章 常數、靜態成員與朋友關 係 13-1 常數物件與成員 13-1 常數物件與成員 13-2 物件成員與巢狀類別 13-2 物件成員與巢狀類別 13-3 靜態成員資料與函數

13-1 13-1 常數物件與成員常數物件與成員 -- 說明說明 C++C++ 語言的語言的 constconst 關鍵字可以用來修飾變關鍵字可以用來修飾變

數、函數、函數參數、指標、物件和成員數、函數、函數參數、指標、物件和成員函數等,例如:函數等,例如: constconst 修飾的變數是宣告修飾的變數是宣告常數,在函數的參數使用常數,在函數的參數使用 constconst ,表示函,表示函數中不允許更改參數值。數中不允許更改參數值。

對於物件來說,對於物件來說, constconst 關鍵字可以授予物關鍵字可以授予物件權限,因為我們可以使用件權限,因為我們可以使用 constconst 關鍵字關鍵字來限制物件不能修改,或指定成員函數不來限制物件不能修改,或指定成員函數不能修改物件內容。能修改物件內容。

Page 3: 第 13 章 常數、靜態成員與朋友關 係 13-1 常數物件與成員 13-1 常數物件與成員 13-2 物件成員與巢狀類別 13-2 物件成員與巢狀類別 13-3 靜態成員資料與函數

13-1 13-1 常數物件與成員常數物件與成員 -- 常數成員資常數成員資料與函數料與函數 (( 說明說明 ))

在在 C++C++ 類別除了建構子和解構子外,成員資料類別除了建構子和解構子外,成員資料和函數都可以使用和函數都可以使用 constconst 關鍵字來修飾。例如:關鍵字來修飾。例如:帳戶類別帳戶類別 accountaccount 的宣告,如下所示:的宣告,如下所示:

class account {class account {private:private: double amount;double amount; const double rate;const double rate;public:public: account(double a, double r);account(double a, double r); double getInterest() const;double getInterest() const; void printAccount() const;void printAccount() const;};};

Page 4: 第 13 章 常數、靜態成員與朋友關 係 13-1 常數物件與成員 13-1 常數物件與成員 13-2 物件成員與巢狀類別 13-2 物件成員與巢狀類別 13-3 靜態成員資料與函數

13-1 13-1 常數物件與成員常數物件與成員 -- 常數成員資常數成員資料與函數料與函數 (( 初始常數值初始常數值 ))

對於類別中的常數,我們只能在建構子使對於類別中的常數,我們只能在建構子使用成員初始語法(用成員初始語法( Member Initializer Member Initializer SyntaxSyntax )來指定其值,如下所示:)來指定其值,如下所示:

account::account(double a,double r) : rate(r) account::account(double a,double r) : rate(r) ,amount(a) ,amount(a)

{ }{ } 上述建構子「上述建構子「 :: 」符號之後就是成員初始語」符號之後就是成員初始語

法,因為初始多個成員函數,所以使用法,因為初始多個成員函數,所以使用「「 ,, 」逗號分隔。」逗號分隔。

Page 5: 第 13 章 常數、靜態成員與朋友關 係 13-1 常數物件與成員 13-1 常數物件與成員 13-2 物件成員與巢狀類別 13-2 物件成員與巢狀類別 13-3 靜態成員資料與函數

13-1 13-1 常數物件與成員常數物件與成員 -- 常數物件常數物件 在使用類別宣告物件變數時,也可以使用在使用類別宣告物件變數時,也可以使用

constconst ,如下所示:,如下所示:const date open(30, 1, 2006);const date open(30, 1, 2006);

上述物件變數上述物件變數 openopen 是一個常數物件,表是一個常數物件,表示物件不允許修改,換句話說,常數物件示物件不允許修改,換句話說,常數物件一定擁有常數的成員函數。一定擁有常數的成員函數。

Page 6: 第 13 章 常數、靜態成員與朋友關 係 13-1 常數物件與成員 13-1 常數物件與成員 13-2 物件成員與巢狀類別 13-2 物件成員與巢狀類別 13-3 靜態成員資料與函數

13-2 13-2 物件成員與巢狀類別物件成員與巢狀類別 13-2-1 13-2-1 物件成員物件成員 13-2-2 13-2-2 巢狀類別巢狀類別

Page 7: 第 13 章 常數、靜態成員與朋友關 係 13-1 常數物件與成員 13-1 常數物件與成員 13-2 物件成員與巢狀類別 13-2 物件成員與巢狀類別 13-3 靜態成員資料與函數

13-2-1 13-2-1 物件成員物件成員 -student-student 類別類別 在在 C++C++ 類別宣告的成員資料除了可以使用資料類別宣告的成員資料除了可以使用資料

型態、結構和陣列變數外,也可以使用其他類別型態、結構和陣列變數外,也可以使用其他類別的物件變數。例如:的物件變數。例如: studentstudent 類別的宣告擁有類別的宣告擁有datedate 物件的成員資料,如下所示:物件的成員資料,如下所示:

class student {class student {private:private: int id;int id; double test1, test2, test3;double test1, test2, test3; date *birthday;date *birthday; double getAverage() const;double getAverage() const;public:public: student(int id, int d, int m, int y);student(int id, int d, int m, int y); void setTest(double t1, double t2, double t3);void setTest(double t1, double t2, double t3); void printStudent() const;void printStudent() const;};};

Page 8: 第 13 章 常數、靜態成員與朋友關 係 13-1 常數物件與成員 13-1 常數物件與成員 13-2 物件成員與巢狀類別 13-2 物件成員與巢狀類別 13-3 靜態成員資料與函數

13-2-1 13-2-1 物件成員物件成員 -date-date 類別類別 datedate 類別宣告,如下所示:類別宣告,如下所示:

class date {class date {

private:private:

int day, month, year;int day, month, year;

public:public:

date(int d, int m, int y); date(int d, int m, int y);

void printDate() const;void printDate() const;

};};

Page 9: 第 13 章 常數、靜態成員與朋友關 係 13-1 常數物件與成員 13-1 常數物件與成員 13-2 物件成員與巢狀類別 13-2 物件成員與巢狀類別 13-3 靜態成員資料與函數

13-2-2 13-2-2 巢狀類別巢狀類別 -- 說明說明 巢狀類別(巢狀類別( Nested ClassNested Class )強調類別之)強調類別之

間的組成關係,例如:學生擁有成績資料,間的組成關係,例如:學生擁有成績資料,所以所以 testtest 類別屬於類別屬於 studentstudent 類別的一部分。類別的一部分。

studentstudent 類別擁有成員類別類別擁有成員類別 testtest 的「內層的「內層類別」(類別」( Inner ClassesInner Classes ),而),而 studentstudent是巢狀類別的「外層類別」(是巢狀類別的「外層類別」( Enclosing Enclosing ClassClass ),內層類別可以位在),內層類別可以位在privateprivate 、、 protectedprotected (第(第 1515 章說明)和章說明)和publicpublic 區塊。區塊。

Page 10: 第 13 章 常數、靜態成員與朋友關 係 13-1 常數物件與成員 13-1 常數物件與成員 13-2 物件成員與巢狀類別 13-2 物件成員與巢狀類別 13-3 靜態成員資料與函數

13-2-2 13-2-2 巢狀類別巢狀類別 -- 範例範例class student { // studentclass student { // student 外層類別宣告外層類別宣告private:private: int id;int id; class test { // testclass test { // test 內層類別宣告 內層類別宣告 private:private: double score;double score; public:public: double getScore() const { return score; }double getScore() const { return score; } void setScore(double s) { score = s; }void setScore(double s) { score = s; } };}; test quiz;test quiz;public:public: student(int no) : id(no) {}student(int no) : id(no) {} void setScore(double t);void setScore(double t); void printStudent() const;void printStudent() const;};};

Page 11: 第 13 章 常數、靜態成員與朋友關 係 13-1 常數物件與成員 13-1 常數物件與成員 13-2 物件成員與巢狀類別 13-2 物件成員與巢狀類別 13-3 靜態成員資料與函數

13-2-2 13-2-2 巢狀類別巢狀類別 -- 存取說明存取說明 內層類別如果位在內層類別如果位在 privateprivate 區塊,其存取範圍只區塊,其存取範圍只

限外層類別之內;如果位在限外層類別之內;如果位在 publicpublic 區塊,其存取區塊,其存取範圍是全域。範圍是全域。

內層類別如果位在內層類別如果位在 privateprivate 區塊,外層類別的成區塊,外層類別的成員並不能存取或呼叫內層類別宣告成員並不能存取或呼叫內層類別宣告成 privateprivate 的的成員,只能存取宣告成成員,只能存取宣告成 publicpublic 的成員。例如:的成員。例如:printStudent()printStudent() 成員函數不能直接存取成員資料成員函數不能直接存取成員資料scorescore ,需要呼叫,需要呼叫 testtest 類別的類別的 getScore()getScore() 成員成員函數,才能取得成績資料。函數,才能取得成績資料。

內層類別如果位在內層類別如果位在 publicpublic 區塊,外層類別的成員區塊,外層類別的成員同樣不能存取或呼叫內層類別宣告成同樣不能存取或呼叫內層類別宣告成 privateprivate 的的成員,不過成員,不過 publicpublic 成員的存取範圍則是全域。成員的存取範圍則是全域。

Page 12: 第 13 章 常數、靜態成員與朋友關 係 13-1 常數物件與成員 13-1 常數物件與成員 13-2 物件成員與巢狀類別 13-2 物件成員與巢狀類別 13-3 靜態成員資料與函數

13-3 13-3 靜態成員資料與函數靜態成員資料與函數 -- 說明說明 在在 C++C++ 的類別宣告中,宣告成的類別宣告中,宣告成 staticstatic 的的

變數和函數是屬於類別。變數和函數是屬於類別。 當建立物件時,並不會替每一個物件建立當建立物件時,並不會替每一個物件建立

獨立的靜態成員資料與函數,所有此類別獨立的靜態成員資料與函數,所有此類別建立的物件,都是使用同一份靜態成員變建立的物件,都是使用同一份靜態成員變數和呼叫同一個靜態函數。數和呼叫同一個靜態函數。

Page 13: 第 13 章 常數、靜態成員與朋友關 係 13-1 常數物件與成員 13-1 常數物件與成員 13-2 物件成員與巢狀類別 13-2 物件成員與巢狀類別 13-3 靜態成員資料與函數

13-3 13-3 靜態成員資料與函數靜態成員資料與函數 -- 宣告類宣告類別的靜態成員資料與函數別的靜態成員資料與函數

靜態成員資料與函數是使用靜態成員資料與函數是使用 staticstatic 關鍵字進行宣關鍵字進行宣告。例如:告。例如: studentstudent 類別新增靜態變數類別新增靜態變數teacherNoteacherNo 、、 countcount 和靜態成員函數和靜態成員函數getStudentCount()getStudentCount() ,如下所示:,如下所示:

class student {class student {private:private: ……… ……… static int count;static int count;public:public: ………… ………… static int teacherNo;static int teacherNo; static int getStudentCount() { return count; };static int getStudentCount() { return count; };};};

Page 14: 第 13 章 常數、靜態成員與朋友關 係 13-1 常數物件與成員 13-1 常數物件與成員 13-2 物件成員與巢狀類別 13-2 物件成員與巢狀類別 13-3 靜態成員資料與函數

13-3 13-3 靜態成員資料與函數靜態成員資料與函數 -- 初始靜初始靜態資料態資料

在在 ANSI-C++ANSI-C++ 類別宣告中的靜態資料都只類別宣告中的靜態資料都只有宣告,並沒有真正定義變數和指定初值,有宣告,並沒有真正定義變數和指定初值,我們需要額外初始類別的靜態變數,其位我們需要額外初始類別的靜態變數,其位置是在類別宣告外的全域變數,如下所示:置是在類別宣告外的全域變數,如下所示:int student::count = 0;int student::count = 0;int student::teacherNo = 200;int student::teacherNo = 200;

上述程式碼使用範圍運算子「上述程式碼使用範圍運算子「 :::: 」來定義」來定義靜態變數和指定初值。靜態變數和指定初值。

Page 15: 第 13 章 常數、靜態成員與朋友關 係 13-1 常數物件與成員 13-1 常數物件與成員 13-2 物件成員與巢狀類別 13-2 物件成員與巢狀類別 13-3 靜態成員資料與函數

13-3 13-3 靜態成員資料與函數靜態成員資料與函數 -- 存取靜存取靜態資料與呼叫靜態函數態資料與呼叫靜態函數

在程式碼存取類別的靜態變數和呼叫靜態在程式碼存取類別的靜態變數和呼叫靜態函數時,也需要使用範圍運算子,如下所函數時,也需要使用範圍運算子,如下所示:示:cout << "\ncout << "\n 學生數學生數 (student): " << (student): " <<

student::getStudentCount();student::getStudentCount();

student::teacherNo = 201;student::teacherNo = 201;

Page 16: 第 13 章 常數、靜態成員與朋友關 係 13-1 常數物件與成員 13-1 常數物件與成員 13-2 物件成員與巢狀類別 13-2 物件成員與巢狀類別 13-3 靜態成員資料與函數

13-4 13-4 朋友關係朋友關係 13-4-1 13-4-1 朋友函數朋友函數 13-4-2 13-4-2 朋友類別朋友類別

Page 17: 第 13 章 常數、靜態成員與朋友關 係 13-1 常數物件與成員 13-1 常數物件與成員 13-2 物件成員與巢狀類別 13-2 物件成員與巢狀類別 13-3 靜態成員資料與函數

13-4 13-4 朋友關係朋友關係 -- 說明說明 C++C++ 語言的朋友關係可以分為朋友函數語言的朋友關係可以分為朋友函數

(( Friend FunctionsFriend Functions )和朋友類別)和朋友類別(( Friend ClassFriend Class )兩種。程式是使用)兩種。程式是使用friendfriend 關鍵字來宣告和建立函數和類別間關鍵字來宣告和建立函數和類別間的朋友關係。的朋友關係。

朋友關係是朋友關係是 C++C++ 語言一種功能十分強大的語言一種功能十分強大的功能,因為朋友函數或類別擁有權限,可功能,因為朋友函數或類別擁有權限,可以存取其他類別隱藏的成員資料,不過,以存取其他類別隱藏的成員資料,不過,在使用上需要十分注意。在使用上需要十分注意。

Page 18: 第 13 章 常數、靜態成員與朋友關 係 13-1 常數物件與成員 13-1 常數物件與成員 13-2 物件成員與巢狀類別 13-2 物件成員與巢狀類別 13-3 靜態成員資料與函數

13-4 13-4 朋友關係朋友關係 -- 特點特點 朋友關係是由類別所授予:類別朋友關係是由類別所授予:類別 AA 授予函數授予函數 b()b()

或類別或類別 BB 擁有朋友關係,而不是擁有朋友關係,而不是 b()b() 或或 BB 向向 AA 取取得朋友關係。得朋友關係。

朋友關係是單方向:如果朋友關係是單方向:如果 AA 認定認定 BB 是朋友,並不是朋友,並不表示表示 BB 是是 AA 的朋友。的朋友。

朋友關係無法繼承:如果朋友關係無法繼承:如果 AA 是是 BB 的朋友,並不表的朋友,並不表示繼承自示繼承自 AA 的類別的類別 CC 是是 BB 的朋友,關於繼承的說的朋友,關於繼承的說明請參閱第明請參閱第 1515 章。章。

朋友關係沒有遞移性(朋友關係沒有遞移性( TransitiveTransitive ):如果):如果 AA 是是BB 的朋友,的朋友, BB 是是 CC 的朋友,並不表示的朋友,並不表示 AA 是是 CC 的朋的朋友。友。

Page 19: 第 13 章 常數、靜態成員與朋友關 係 13-1 常數物件與成員 13-1 常數物件與成員 13-2 物件成員與巢狀類別 13-2 物件成員與巢狀類別 13-3 靜態成員資料與函數

13-4-1 13-4-1 朋友函數朋友函數 -- 說明說明 對於不屬於對於不屬於 C++C++ 類別的成員函數或一般函類別的成員函數或一般函

數來說,函數並不能存取類別宣告成數來說,函數並不能存取類別宣告成privateprivate 或或 protectedprotected (在第(在第 1515 章說明)章說明)區塊的成員,如果函數需要存取區塊的成員,如果函數需要存取 privateprivate或或 protectedprotected 成員,在成員,在 C++C++ 語言可以使語言可以使用用 friendfriend 關鍵字授予其他函數的朋友關係,關鍵字授予其他函數的朋友關係,即朋友函數。即朋友函數。

不過,朋友函數並不是類別的成員函數,不過,朋友函數並不是類別的成員函數,但是授予朋友關係後,朋友函數可以存取但是授予朋友關係後,朋友函數可以存取類別位在類別位在 privateprivate 和和 protectedprotected 區塊宣告區塊宣告的成員。的成員。

Page 20: 第 13 章 常數、靜態成員與朋友關 係 13-1 常數物件與成員 13-1 常數物件與成員 13-2 物件成員與巢狀類別 13-2 物件成員與巢狀類別 13-3 靜態成員資料與函數

13-4-1 13-4-1 朋友函數朋友函數 -- 一般函數的朋友一般函數的朋友函數函數

第第 55 章的函數也可以成為類別的朋友函數。例如:章的函數也可以成為類別的朋友函數。例如:類別類別 circlecircle 授予授予 getRadius()getRadius() 函數成為它的朋友函數成為它的朋友函數,如下所示:函數,如下所示:

class circle {class circle {private:private: int radius;int radius;public:public: circle(int r) : radius(r) {}circle(int r) : radius(r) {} void print(point &p);void print(point &p); friend int getRadius(circle &c);friend int getRadius(circle &c);};};

Page 21: 第 13 章 常數、靜態成員與朋友關 係 13-1 常數物件與成員 13-1 常數物件與成員 13-2 物件成員與巢狀類別 13-2 物件成員與巢狀類別 13-3 靜態成員資料與函數

13-4-1 13-4-1 朋友函數朋友函數 -- 成員函數的朋友成員函數的朋友函數函數

類別的成員函數也可以宣告成朋友函數。例如:類別的成員函數也可以宣告成朋友函數。例如:在在 pointpoint 類別授予類別授予 circlecircle 類別的類別的 print()print() 成員函成員函數為朋友關係,如下所示:數為朋友關係,如下所示:

class point {class point {

private:private:

int x, y;int x, y;

public:public:

…… ……

friend void circle::print(point &p); friend void circle::print(point &p);

};};