iT邦幫忙

2021 iThome 鐵人賽

0
Arm Platforms

STM32 基礎入門教學系列 第 25

【Day25】:從struct進化成class的物件導向技巧(上)

本篇與STM32相關性不大
會有這個章節其實是有原因的...有一天我請學長幫我看一下程式的時候,請我讓馬達開始旋轉,結果意外的看到我打的語法是

motor.rotate();

他立馬就說:「你寫C++喔?太好了吧」
為什麼學長一看到這一行就知道我寫C++呢?以及這樣寫哪裡好呢?這就要提到物件導向對於大程式的種種好處了!

物件導向OOP(Object-oriented programming)

物件導向是一種寫程式的概念,主要的精神就是將日常生活中的物件(object)中的概念,應用於程式設計。以一種更生活化、可讀性更高的設計觀念來進行。用這種方式會讓程式更容易擴充、修改與維護。

類別

類別的概念衍伸於C的結構,是使用者定義的抽象型態,可以打包許多資料型別成為一個新的型別。例如我們可以設計一個車子的類別,底下有兩個變數分別為l1、l2儲存車子輪子間的距離(長與寬),另外還有x、y來儲存現在現在移動的距離、還有dir記住現在車子移動的方向...。利用這種方式來描述這個物件,是不是更直觀啊。

class Car {
	double l1, l2;
	double x;
	double y;
	int dir;
};

但是到目前為止,這些功能用C的struct都可以完成,接下來要加一些C語言不具備的功能。
C++更人性化的一個設計就是他具有「成員函式」。既然他是一個物件,那不同物件就應該要有操縱物件的「方法」,這個方法就稱為成員函式,更白話一點就是可以在類別內宣告函式。
例如:

class Car {
	double l1, l2;
	double x;
	double y;
	int dir;
    //member function 成員函式
	void move(double vx, double vy, double w0){
        /*
        函式內容
        */
    }
	void stop(){
        /*
        函式內容
        */
    }
};

我們的car物件具有兩種使用方法,分別是讓他以某一個速度移動,以及讓車子停下來。宣告的方法與一般函式的宣告沒什麼不一樣。而在實際寫程式時,為了讓整個看起來更乾淨,通常會將成員函式的內容拉到其他地方來寫,只在類別內做宣告,如下:

class Car {
	double l1, l2;
	double x;
	double y;
	int dir;
    //member function 成員函式
	void move(double vx, double vy, double w0);
	void stop();
};

void Car::move(double vx, double vy, double w0){
    /*
    函式內容
    */
}
void Car::stop(){
    /*
    函式內容
    */
}

這樣整個Class的內容就像一個手冊,可以看到Car這個物件的使用方法。在程式外面宣告時需要在函式名稱的開頭加上
" 物件名稱:: " 就可以表示要定義哪一個物件的函式。
假設我們已經成功實做出這兩個函式,我們只要用以下的方法就可以對car這個物件使用函式了。

int main(){
    Car car;
    car.stop();
}

先宣告一個Car型別的物件(習慣上自己定義的型別開頭會大寫),使用的方法就與C語言的struct相同,變數與成員函式都可以用「.」這個方式存取或使用。

在程式設計時,我們可以先宣告一個物件,接著先列出這個物件要有哪些使用方法,例如上面車子的物件,就可以有好幾種使用的方法,可以讓車子走,可以讓車子旋轉,可以讓車子停下來...,列出來後,我們再來分別實作出這些函式,例如要讓車子往前,我們可能就要在函式內讓四個輪子的馬達以相同的速度旋轉。只要你順利完成這個函式,以後就不要在動這個部份了,以後我們的工作就是「使用」這些函式。

封裝

接下來就要講到物件導向的三大重要概念之一-封裝
封裝的意思就是將某些變數封裝在類別中,將資料隱藏起來,不讓外界任意的使用,這麼做有個很大的好處,那就是我們不會在其他地方任意的更改到這個值,假設有很多人共同撰寫一個程式,如果有人不小心動到你的變數,那麼你可能會毫無發覺,但程式怎麼樣跑都是錯誤的。因此將資料隱藏起來是一個很重要的概念。
C++有三種存取級別,分別為private、protected、public,寫在程式碼後,就可以限制底下變數的存取權限,如下:

class Car{
    private:
        /****/
    protected:
        /****/
    public:
        /****/
}

public代表此一區塊屬於公共成員,也就是在程式碼的任何位置都可以取用這個變數,在C語言當中的struct就可以想像成C++的class,只是裡面的所有變數都是public的,沒有任何的限制。再來private代表此一區塊屬於私有成員,具有最高的保護層級,也就是此區塊內的成員只能被物件的成員函式存取。protected代表此一區塊是屬於保護成員,只能讓繼承此類別的新類別能使用,是專為繼承關係訂做的一種存取模式。目前我們可以先不管它。
這樣的存取限制是在編譯過程中就會抓出來的錯誤,不是在程式執行中才限制,因此如果該變數是private的存取權,你在其他類別當中使用,就會出現error。
在寫程式時,雖然資料隱藏對大程式來說很重要的,但是使用上會有一些麻煩,如果只是一個人寫,你也很清楚變數在哪裡被更動的話,可以先將所有的變數、成員函式以public的方式宣告。(c++中,如果類別內沒有加上存取權限,預設都是private)。

資料來源

  1. 吳燦銘(2019)。C++程式設計與運算思維事務。新北市:博碩。

上一篇
【Day24】:TIM-輸入捕獲
下一篇
【Day26】:從struct進化成class的物件導向技巧(下)
系列文
STM32 基礎入門教學30

尚未有邦友留言

立即登入留言