網頁

2022/8/2

C++ 宣告類別 declare class

C++宣告類別(class)的方式如下。


Class類似struct為多種資料型態的組合成的新型態,但除了資料成員(屬性)還可包含函式成員(方法)。


宣告類別 declare class

宣告類別的語法如下:

  • class - 宣告類別的關鍵字。
  • ClassName - 類別名稱,習慣以大駝峰命名UpperCamelCase
  • access_specifier_1-2 - 存取修飾符(access specifier),分為publicprotectedprivate。若無存取修飾符則預設為private
  • member1-2 - 類別成員,分為屬性及方法:
    • 屬性(attributes) - 即資料成員,用來儲存物件的資料狀態。
    • 方法(methods) - 即函式成員,用來改變或取得物件的資料狀態。˙

class ClassName {
    access_specifier_1:
        member1;
    access_specifier_2:
        member2;
    ...
}

下面宣告一個類別Car中有privatepublic存取修飾符。
private修飾屬性modelspeed
public修飾建構式Car()Car(string model, int speed)及方法GetModel()GetSpeed()SpeedUp()SlowDown()

main.cpp

#include <string>
using namespace std;

class Car {
    private:
        // 屬性 attributes
        string model;
        int speed;

    public:
        // 建構式 constructors
        Car() { speed = 0; }
        Car(string model, int speed) : model(model), speed(speed) {}

        // 方法 methods
        string GetModel() { return model; }
        int GetSpeed() { return speed; }
        void SpeedUp() { speed++; }
};


成員存取修飾符 member access specifiers

成員存取修飾符的用途為控制成員是否能從類別外存取:

  • public - 成員可在類別外、繼承類別、類別內存取。
  • protected - 成員可在繼承類別、類別內存取。
  • private - 成員僅可在類別內存取。

例如GetModel()方法為public,所以可以在類別外存取;而model屬性為private則在類別外存取時編譯會發生錯誤。

main.cpp

#include <iostream>
#include <string>
using namespace std;

class Car {
    private:
        string model;
        int speed;

    public:
        Car() { speed = 0; }
        Car(string model, int speed) : model(model), speed(speed) {}

        string GetModel() { return model; }
        int GetSpeed() { return speed; }
        void SpeedUp() { speed++; }
};

int main() {
    Car car{"MAZDA CX-30", 0};
    cout << car.GetModel() << endl;
    cout << car.model << endl; // error: 'speed' is a private member of 'Car'

    return 0;
}


方法 methods

C++定義類別的方法有兩種方式,一是在類別中直接定義方法及主體,例如上例;一是在類別中僅定義方法原型(prototype),即僅定義方法名稱、參數型態及數量、回傳型態,然後在類別外定義同方法原型簽章的函式為方法主體,並在函式名稱前加上同類別名稱的作用範圍符(scope operator)Car::

例如下面將建構式及方法主體定義在類別外的函式。

main.cpp

#include <string>
using namespace std;

class Car {
    private:
        string model;
        int speed;

    public:
    	// 建構式原型
        Car();
        Car(string model, int speed);

        // 方法原型
        string GetModel();
        int GetSpeed();
        void SpeedUp();
};

// 建構式主體
Car::Car() { speed = 0; }
Car::Car(string model, int speed) : model(model), speed(speed) {}

// 方法主體
string Car::GetModel() { return model; }
int Car::GetSpeed() { return speed; }
void Car::SpeedUp() { speed++; }


建構式 constructors

建構式是一種特別的方法,用來建立新的類別物件並初始化屬性。建構式的名稱必須與類別名稱相同,且沒有任何返回型態。

例如下面定義了兩個Car的建構式Car()Car(string model, int speed),如函式一樣建構式也可重載(overloading)

無參數的建構式為預設建構式(default constructor),所以Car()為預設建構式。當宣告類別的物件變數時若無初始化敘述(Car car;)、或為空的統一初始化(uniform initialization)敘述(Car car = {};)則呼叫預設建構式來建立物件。

main.cpp

#include <iostream>
#include <string>
using namespace std;

class Car {
    private:
        string model;
        int speed;

    public:
        Car() { speed = 0; } // 預設建構式
        Car(string model, int speed) : model(model), speed(speed) {}

        string GetModel() { return model; }
        int GetSpeed() { return speed; }
        void SpeedUp() { speed++; }
};

int main() {
    Car car1;                        // 呼叫預設建構式
    cout << car1.GetModel() << endl; // "" (空字串)
    cout << car1.GetSpeed() << endl; // 0
    
    Car car2 = {};                   // 呼叫預設建構式
    cout << car2.GetModel() << endl; // "" (空字串)
    cout << car2.GetSpeed() << endl; // 0

    Car car3 = {"MAZDA CX-30", 1};   // 呼叫有參數的建構式
    cout << car3.GetModel() << endl; // MAZDA CX-30
    cout << car3.GetSpeed() << endl; // 1

    return 0;
}

若無建構式進行初始化建立物件,則物件中某些型態的屬性會是任意值。例如下面把建構式移除,則宣告的car物件的speed是不確定的整數值。

main.cpp

#include <iostream>
#include <string>
using namespace std;

class Car {
    private:
        string model;
        int speed;

    public:
        string GetModel() { return model; }
        int GetSpeed() { return speed; }
        void SpeedUp() { speed++; }
};

int main() {
    Car car;
    cout << car.GetSpeed() << endl; // -343938976 (不確定的整數值)

    return 0;
}


範例

下面在主程式以統一初始化語法調用建構式Car(string model, int speed)初始化屬性model的值為"MAZDA CX-30"、speed值為0,建立了一個Car類別的物件car

接著呼叫car.SpeedUp()增加速度。然後調用car.GetModel()取得car.model印出,調用car.GetSpeed()取得car.speed印出。

main.cpp

#include <iostream>
#include <string>
using namespace std;

class Car {
    private:
        string model;
        int speed;

    public:
        Car() { speed = 0; }
        Car(string model, int speed) : model(model), speed(speed) {}

        string GetModel() { return model; }
        int GetSpeed() { return speed; }
        void SpeedUp() { speed++; }
};

int main() {
    Car car{"MAZDA CX-30", 0};
    car.SpeedUp();
    cout << car.GetModel() << endl; // MAZDA CX-30
    cout << car.GetSpeed() << endl; // 1

    return 0;
}

執行後印出以下。

MAZDA CX-30
1


沒有留言:

張貼留言