1. 程式人生 > >一步步分析:C語言如何面向物件程式設計

一步步分析:C語言如何面向物件程式設計

這是道哥的第009篇原創
## 一、前言 在嵌入式開發中,C/C\+\+語言是使用最普及的,在C\+\+11版本之前,它們的語法是比較相似的,只不過C++提供了面向物件的程式設計方式。 雖然C++語言是從C語言發展而來的,但是今天的C\+\+已經不是當年的C語言的擴充套件了,從2011版本開始,更像是一門全新的語言。 ![](https://img2020.cnblogs.com/blog/1440498/202012/1440498-20201220171631311-905219643.png) 那麼沒有想過,當初為什麼要擴展出C\+\+?C語言有什麼樣的缺點導致C\+\+的產生? ![](https://img2020.cnblogs.com/blog/1440498/202012/1440498-20201220171642295-1227799427.png) C++在這幾個問題上的解決的確很好,但是隨著語言標準的逐步擴充,C++語言的學習難度也逐漸加大。沒有開發過幾個專案,都不好意思說自己學會了C++,那些左值、右值、模板、模板引數、可變模板引數等等一堆的概念,真的不是使用2,3年就可以熟練掌握的。 但是,C語言也有很多的優點: ![](https://img2020.cnblogs.com/blog/1440498/202012/1440498-20201220171650260-992105983.png) 其實最後一個優點是最重要的:使用的人越多,生命力就越強。就像現在的社會一樣,不是優者生存,而是適者生存。 ![](https://img2020.cnblogs.com/blog/1440498/202012/1440498-20201220171658610-314159968.png) 這篇文章,我們就來聊聊如何在C語言中利用面向物件的思想來程式設計。也許你在專案中用不到,但是也強烈建議你看一下,因為我之前在跳槽的時候就兩次被問到這個問題。 ## 二、什麼是面向物件程式設計 有這麼一個公式:程式=資料結構+演算法。 C語言中一般使用面向過程程式設計,就是分析出解決問題所需要的步驟,然後用函式把這些步驟一步一步呼叫,在函式中對資料結構進行處理(執行演算法),也就是說資料結構和演算法是分開的。 C++語言把資料和演算法封裝在一起,形成一個整體,無論是對它的屬性進行操作、還是對它的行為進行呼叫,都是通過一個物件來執行,這就是面向物件程式設計思想。 如果用C語言來模擬這樣的程式設計方式,需要解決3個問題: > 1. 資料的封裝 > 2. 繼承 > 3. 多型 #### 第一個問題:封裝 封裝描述的是資料的組織形式,就是把屬於一個物件的所有屬性(資料)組織在一起,C語言中的結構體型別天生就支援這一點。 #### 第二個問題:繼承 繼承描述的是物件之間的關係,子類通過繼承父類,自動擁有父類中的屬性和行為(也就是方法)。這個問題只要理解了C語言的記憶體模型,也不是問題,只要在子類結構體中的第一個成員變數的位置放置一個父類結構體變數,那麼子類物件就繼承了父類中的屬性。 另外補充一點:學習任何一種語言,一定要理解記憶體模型! #### 第三個問題:多型 按字面理解,多型就是“多種狀態”,描述的是一種動態的行為。在C\+\+中,只有通過基類引用或者指標,去呼叫虛擬函式的時候才發生多型,也就是說多型是發生在執行期間的,C++內部通過一個虛表來實現多型。那麼在C語言中,我們也可以按照這個思路來實現。 > 如果一門語言只支援類,而不支援多型,只能說它是基於物件的,而不是面向物件的。 既然思路上沒有問題,那麼我們就來簡單的實現一個。 ## 三、先實現一個父類,解決封裝的問題 Animal.h ``` #ifndef _ANIMAL_H_ #define _ANIMAL_H_ // 定義父類結構 typedef struct { int age; int weight; } Animal; // 建構函式宣告 void Animal_Ctor(Animal *this, int age, int weight); // 獲取父類屬性宣告 int Animal_GetAge(Animal *this); int Animal_GetWeight(Animal *this); #endif ``` Animal.c ``` #include "Animal.h" // 父類建構函式實現 void Animal_Ctor(Animal *this, int age, int weight) { this->age = age; this->weight = weight; } int Animal_GetAge(Animal *this) { return this->age; } int Animal_GetWeight(Animal *this) { return this->weight; } ``` 測試一下: ``` #