文章程式碼顯示

2018年3月14日 星期三

《筆記》談談C++語言 - 5:建構子

private

#include "stdio.h"
#include "stdlib.h"

class GradeBook {

public:
 void setCourseName ( char* name){
  courseName = name;
 }

 char* getCourseName (){
  return courseName;
 }

 void displayMessage(){
  printf("Welcome to [%s] GradeBook", getCourseName() );
 }

private:
 char* courseName;

}myGradeBook;


int main() {

 myGradeBook.setCourseName("Advanced Math");
 myGradeBook.displayMessage();

 return 0;
}


前面我們使用這樣的方式宣告了一個 private 的 courseName,並且沒有給予任何初始値

接著我們試試給予初始値

在 private 直接給初始値

#include "stdio.h"
#include "stdlib.h"

class GradeBook {

public:
 void setCourseName ( char* name){
  courseName = name;
 }

 char* getCourseName (){
  return courseName;
 }

 void displayMessage(){
  printf("Welcome to [%s] GradeBook", getCourseName() );
 }

private:
 char* courseName = "Advanced Math";

}myGradeBook;


int main() {

 //myGradeBook.setCourseName("Advanced Math");
 myGradeBook.displayMessage();

 return 0;
}




建構子


#include "stdio.h"
#include "stdlib.h"

class GradeBook {

public:

 //constructor
 GradeBook(){
  setCourseName("Advanced Math(constructor)");
 }

  void setCourseName ( char* name){
   courseName = name;
  }

  char* getCourseName (){
   return courseName;
  }

  void displayMessage(){
   printf("Welcome to [%s] GradeBook", getCourseName() );
  }

private:
 char* courseName;

};


int main() {

 GradeBook myGradeBook;
 myGradeBook.displayMessage();

 return 0;
}




建構子是一個特殊的成員函式,不能傳回任何數値(包含 void 也不行),且通常宣告在 public 的地方,其功用是在建立物件的同時變成使用建構子將類別物件進行初使化。

建構子的名稱「必須與類別名稱相同」,編譯器才會知道這是建構子函式

C++ 建立每個物件時都要呼叫建構子,以確保程式使用物件前每個物件均已初始化。建立物件時,程式會自動呼叫其類別的建構子。若類別內沒有明確寫出建構子,則編譯器會自動提供一個預設建構子(default constructor),也就是沒有參數的建構子。當物件建立的時候這個預設建構子被觸發,此時物件裡面的資料成員將會被「初使化」,値得注意的是編譯器不會提供任何初使値給物件的基本型別(如 int, float)資料成員(初使化與給初始値是兩回事)

這可能會造成問題,因為一個沒有被賦予初始値的變數可能會被賦予一個未知的値(garbage value)

若資料成員是「其他類別物件」的話,預設建構子會隱含呼叫每個資料成員(其他類別物件)的預設建構子,確保資料成員有正確地初使化。

建構子具有輸入參數

#include "stdio.h"
#include "stdlib.h"

class GradeBook {

public:

 //constructor
 GradeBook(char* str){
  setCourseName(str);
 }

  void setCourseName ( char* name){
   courseName = name;
  }

  char* getCourseName (){
   return courseName;
  }

  void displayMessage(){
   printf("Welcome to [%s] GradeBook", getCourseName() );
  }

private:
        char* courseName;

};


int main() {

 GradeBook myGradeBook("Lesson 1");
 myGradeBook.displayMessage();

 printf("\n");

 GradeBook myGradeBook2("Lesson 2");
 myGradeBook2.displayMessage();

 return 0;
}



不知道有沒有人有疑問,既然都是初使化,為什麼還要使用建構子呢? 在 private 的地方直接給初始値不就好了嗎(如前面的例子)

上方的例子就體現出使用建構子的好處,當我們用同一個類別來建立兩個不同的物件 myGradeBook 及 myGradeBook2 時,在建立物件的同時可以利用建構子給資料成員不同的初始値,這是使用前面的方法做不到的。

在一個類別設定建構子以確保資料成員都被正確的初使化(給予正確的初使值)是很重要的。

面對一個沒有定義適當建構子的類別,使用者就必須在建立物件後再對資料成員各別進行設定(初使值)。然而這樣的使用體驗顯然是不適當的,萬一使用者在沒有正確對資料成員進行初使化的情況下就呼叫了成員函式,則得到的結果是不可預期的(可能會導致程式崩潰等等的問題)


↓↓↓ 連結到部落格方針與索引 ↓↓↓

Blog 使用方針與索引