三.c++實現流水燈
四.c實現物件導向的典型案例分析
五.總結
流水燈是微控制器入門學習的小專案,實現邏輯很簡單。往往我們使用c語言面向過程的方法就可以很容易的實現,本文借助流水燈這個簡單的場景來講解物件導向的程式設計思想,並比較c和c++實現方法的區別。都說c語言是非物件導向的語言,這是不準確的,物件導向是一種程式設計思想,和使用什麼語言無關,正如linux核心如此龐大的工程也是使用c實現的,並且其中使用了大量的物件導向的程式設計方法。因此只能說c語言並不原生支援物件導向程式設計,而c++原生支援物件導向程式設計,這就導致了使用c實現物件導向會更複雜一些,但完全可以實現,下面就結合**分析比較:
#include
#include
#include
//定義流水燈的個數
#define n 7
typedef
void
(*pfunc_ledon_t)
(int n)
;//定義ledon函式模板
typedef
void
(*pfunc_ledoff_t)
(int n)
;//定義ledoff函式模板
//led亮操作函式
void
ledon
(int n)
//led滅操作函式
void
ledoff
(int n)
//封裝led類
struct led
;int
main
(void
)//使用物件呼叫成員函式的方法實現流水燈
while(1
)printf
("----------------\r\n");
sleep
(1000);
}}return0;
}
led0on
led1off
led2off
led3off
led4off
led5off
led6off
----
----
----
----
led0off
led1on
led2off
led3off
led4off
led5off
led6off
----
----
----
----
led0off
led1off
led2on
led3off
led4off
led5off
led6off
----
----
----
----
led0off
led1off
led2off
led3on
led4off
led5off
led6off
----
----
----
----
上面的**很簡單,核心思想就是將led看作乙個物件,這個物件包括乙個屬性(led的編號)和兩個操作(ledon、ledoff)。然後使用struct結構體將屬性和操作封裝起來構成乙個led類。有了類就可以例項化物件myled[0],myled[1]…myled[n-1];,例項化物件之後就需要對這個物件的屬性和操作初始化,也就是給成員變數賦初值,將操作函式指向具體的實現函式,這是c和c++的最大不同(實際上在c中struct更像是一種打包的方式,並不考慮其中函式和變數之間的操作關係)。在對物件完成初始化之後就可以操作其屬性和方法了:myled[j].vledon(myled[j].led_num); //執行亮燈函式
myled[j].vledoff(myled[j].led_num); //執行關燈函式
#include
#include
#include
#include
"test.h"
#include
using
namespace std;
//定義流水燈的個數
#define n 3
//定義乙個led類
class
led//有參建構函式,初始化led編號
led(
int my_led_num)
:led_num
(my_led_num)
//對led物件的操作
void
ledon
(void
)void
ledoff
(void
)private
://led的屬性
int led_num;
//代表led的編號};
intmain
(void);
//迴圈建立n個led物件
for(
int i =
0; i < n; i++
)//使用物件呼叫成員函式的方法實現流水燈
while(1
) cout <<
"----------------"
<< endl;
sleep
(1000);
}}return0;
}
led0on
led1off
led2off
----
----
----
----
led0off
led1on
led2off
----
----
----
----
led0off
led1off
led2on
----
----
----
----
led0on
led1off
led2off
----
----
----
----
led0off
led1on
led2off
----
----
----
----
可以看出c++的實現思路和c完全相同,也是建立led類,例項化物件,呼叫成員函式。但是c++實現起來更加簡潔明瞭,這就是因為c++原生支援物件導向程式設計,在我們使用class建立類的時候,屬性led_num和兩個操作函式之間就自動建立了某種內在聯絡,並且我們可以將函式的實現定義在類中而不需要再像c一樣指向具體的實現函式,後面使用物件執行操作就基本一致了。通過比較我們可以發現c和c++都可以很好的實現物件導向程式設計,但是很顯然c++封裝的更好些,且更加簡潔明瞭,因此在我們應對更大規模的複雜工程時c++的優勢更加能得以體現。
在linux中進行驅動程式設計的時候,會使用struct封裝某個驅動類,並且定義好操作函式的介面形式,驅動物件的例項化操作以及結構體指標的實現方法由驅動開發人員去實現,也就是linux核心提供了物件導向的封裝方法並且規定了操作函式的引數列表及型別,開發人員只需要例項化其即可。
例如linux封裝的檔案操作類,其中一些屬性和操作的需要開發人員在實際使用中去例項化它:
struct file_operations
;
比如我們自定義乙個file_operations結構體變數,並且去填充:
static
const
struct file_operations test_fops =
;
我們需要去例項化 test_chrdev_open,test_chrdev_release, test_chrdev_read,test_chrdev_write等這些函式,然後系統會將我們的這些操作傳遞給核心去呼叫。比如實現test_chrdev_write函式如下:
static ssize_t test_chrdev_write
(struct file*file,
const
char __user *ubuf,size_t count,loff_t *ppos)
liteos中支援linux,liteos,macos,novos,ucos_ii等操做系統核心,那麼liteos是怎樣同時支援這這些不同作業系統核心的呢?這就是物件導向思想的封裝,一套介面可以有不同的實現,不同的作業系統對同乙個函式可能有不同的實現方法,那麼在liteos中就定義了乙個公共介面的結構體,在例項化物件的時候,可以將介面函式(結構體成員函式)指向不同作業系統的實現函式,這樣就實現了對不同作業系統的呼叫。在liteos中osal檔案中就是封裝了公共介面。簡單展示如下:
tyepdef struct
tag_os_ops;
每個不同的os實現上述函式的具體方法不同,但是可以通過tag_os_ops例項化出不同os的物件,並在具體的物件中例項化出具體的操作函式(明確函式指標的指向)。
例如gpio的初始化:
tyepdef struct
gpio_inittypedef;
以上是hal庫封裝好的類屬性。
在gpio初始化的時候就會定義例項化物件並設定這些屬性:
static
void
mx_gpio_init
(void
)
最後呼叫hal_gpio_init是非物件導向方法,因為hal_gpio_init不是類的操作函式,這是因為c本身一種物件導向語言,強行物件導向反而會更複雜,這是一種折中方案。
再次強調物件導向是一種程式設計思想,和使用什麼語言無關。使用c和c++都可以很好的實現物件導向程式設計,只是實現的複雜度不同。因此c++更適合應用於解決複雜工程專案中。
led流水燈的實現程式
led流水燈的實現是目前微控制器程式中最容易實現的程式。1.延時的實現 由於人眼的視覺暫留大約在2us左右,所以,在實現流水燈的時候有乙個重要的問題 延時。如果不延時,在人眼看來,led是全亮的。延時有兩種方式可以實現 1.呼叫intrins.h nop 延遲1us2.自己寫乙個延遲函式 t 0 t...
C 物件導向思想(一)
相比c,c 多出來一些東西來,類定義 繼承 過載 覆蓋 類動態編譯 抽象類虛函式 模板。這些東西非常有用,但怎麼用,像我這種小白,就有些難過了,世界最遙遠的距離就是雖然學習了物件導向,可是用起來還是如同面向過程一樣粗暴 首先我們需要了解什麼是物件導向思想 物件便是我們接觸的事物,有屬性有動作。而物件...
C 物件導向思想 OOP
物件導向的基本思想是 從現實世界中客觀存在的事物出發來構造軟體系統,並在系統的構造中盡可能地運用人類的自然思維方式。物件導向更加強調運用人類在日常生活的邏輯思維中經常採用的思想方法與原則,如抽象 分類,繼承 聚合 多型等。oop 的一條基本原則是 電腦程式是由單個能夠起到子程式作用的單元或物件組合而...