在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

循環隊列C語言面向對象實現

技術讓夢想更偉大 ? 來源:CSDN-夏日白云 ? 2023-04-04 09:47 ? 次閱讀

前言

學習完《Test-Driven Development for Embedded C》后對C語言中的面向對象開發又多了一層理解,過兩天可能專門出個博客來說說新的理解。

而我已經按照更面向對象的方法大改了原來的那個環形緩沖區模塊,考慮到整個結構已經完全不同了,所以直接棄用了原來那個模塊,新模塊直接重新開始記版本號。

Buffer模塊為了通用,定義了前后都可以進出,想當成隊列來用比如可以入隊用BackIn,出隊用FrontOut;相當成棧來用比如可以入棧用BackIn,出棧用BackOut。當然,第三篇中我會給出Queue類,并把Buffer類適配為了Queue類,這樣可能用起來更舒服些,雖然當然有額外的開銷。

緩沖區介紹

實際項目中我們常常會需要一小塊區域來暫存一些數據,可能是用來緩存使用,可能是用來線程間通信,我們把其稱為緩沖區/Buffer。這塊區域可能是先入先出的(隊列)也可能是先入后出的(棧),但反正最后都可以抽象為一個可以在頭或尾存取數據的內存區域。

緩沖區的具體實現方式一般有鏈表和數組,當不能確定需要的緩沖區大小時使用鏈表較好,能確定時使用數組可以節省很多動態分配內存的開銷。

而在具體實現上我們常常會使用環形緩沖區,環形緩沖區就是一個邏輯上環形的區域,因為其(邏輯上)是環形的,所以不需要在內部元素變動的時候需要移動內部剩下的元素。這樣就使元素進出頭尾的時間復雜度只有O(1),效率十分的高,在通信等領域應用頻繁。

模塊類圖

以下是目前整個模塊的類圖。

a0e3e45c-d246-11ed-bfe3-dac502259ad0.png

模塊設計思路簡介

緩沖區是個很常見的需求,即對一塊邏輯上環形的區域的頭尾進行In和Out操作,以緩存各種類型的數據。對調用者來說,并不需要知道其使用的模塊/類內部實際是怎么實現的,只需要知道這個模塊/類實現哪幾個方法,這幾個方法是干什么用的就行(其實就是所謂的面向接口編程)。因此,需要為環形緩沖區定義通用的接口。

在一個略大的項目中我們常常需要在多處使用環形緩沖區。所以在這次的實現中我并沒有使用單例的方式來實現這個模塊,而是直接默認是多例的方式,不同的實現各自提供Create方法來返回對象引用,Destroy方法來銷毀。

實際開發中有時會需要混用多種實現,比如有的你希望使用一個RAM數組,有的想用鏈表,甚至有的是使用Flash來存儲的等。而只要接口相同,調用者不需要知道具體的實現細節,只需要你給他傳遞一個實現了這個接口的對象就行。這其實就實現了不同模塊間的解耦。而為了實現在同一個C工程中調用同一個接口能實際調用不同的實現(即多態),這就需要使用虛表技術。這里就不展開了。

再考慮一個很實際的需求,在CodeWarrior對S12X的編程中,為了節省非分頁的RAM,我常想要把這個環形緩沖區放在分頁的RAM中,這樣,兩種環形緩沖區可能唯一的差別就是具體訪問某個元素的方式是使用普通指針還是rptr指針,如果分別寫一個實現,就會有大量的冗余代碼。出于程序員的自我修養,肯定得把這些通用的部分給抽象出來。用繼承的方式實現代碼的復用。

好像前面說的有點混亂。簡而言之,就是按照面向對象的思想,定義不同層次的接口,通過虛表實現多態,通過類繼承盡可能復用代碼,最終實現這個完整的模塊。

我們可以照著類圖看看目前我的抽象方式。首先所有對象都會有個Destroy方法,所以object接口對其進行了定義。這里我沒有專門再定義一個Object虛類,后面可能會抽象出來。而最主要的一個基類叫做Container(容器),所有的容器都要實現getCapacity和getCount接口。而isEmpty和isFull其實是通過調用這兩個虛方法返回結果的。

而后虛類BufferTYPE繼承了Container虛類,并(虛)實現了環形緩沖區的7個通用方法,包括檢查頭/尾元素(Front和Back)、從頭/尾取出元素(FrontOut和BackOut)、往頭/尾放入元素(FrontOut和BackOut)以及清空緩沖區(Cleanup)。

TYPE只是一個代號,使用時要替換成實際類型。目前我實現了UINT8、UINT16、UINT32的。如果需要使用其他類型,如果類型的size為8、16、32,建議直接適配一下就好(其實就是對同樣size的進行強制類型轉換一下,BufferChar給出了一個示例),這樣可以盡可能地實現代碼復用,如果是其他特殊的,那就照著源代碼中的自己擴展一下吧,主要是C語言沒有模板功能,只好直接在名字中標記上類型來區分。

然后繼承的BufferTYPEIndexed虛類要實現索引器接口,其是所有能通過索引直接訪問的Buffer的基類。

BufferArrayShare類繼承BufferTYPEIndexed類并實現了所有通過類數組操作來實現的Buffer類的通用部分,其調用索引器來訪問數組元素,這樣就實現了不同訪問方式的復用。與之相對的則是子類BufferTypeArray和BufferTypeArrayR分別實現了位于直接訪問區的數組和分頁區數組的索引器。

而末尾的3個實現類則主要負責內存的管理部分,動態分配實例并實現對應的Destroy方法,然后調用父類的Init方法來實現完整的類。項目中可以同時使用這幾個類。

當然,因為高度的面向對象,導致有大量的小文件,這其實和面向對象語言提供的各種類有一堆文件一個道理。好在使用起來還是很方便的。

如果只是使用的話建議不需要具體了解內部的實現,根據類圖了解下繼承關系,看看每個類的接口的描述。然后直接調用實例的方法就行。那一堆小文件就直接全部拖到項目中就好。(PS.沒有用到的類是不會鏈接進去占用內存的,所以直接扔進項目就好了,沒用到就沒用到。)

現在會有這些文件。

a0fd80c4-d246-11ed-bfe3-dac502259ad0.png

編程約定

接口定義在.h頭文件中,如名字中帶有Private則代表其中的接口為private或protect的,非開發者不應該使用,否則為public的,供給用戶使用。

由于C語言本身沒有OO這個概念,所以類的方法以這種方式命名,這樣可以很直觀地知道是哪個類的方法:

類名_方法();

另,對于多例的類,第一個參數為被調用方法的實例,其后跟其他參數。

如BufferUINT8的Back方法的簽名如下:

uint8_t BufferUINT8_Back   (BufferUINT8 buf);
1

子類實例可以直接調用父類方法。如:

uint8_t arr[ARRSIZE];
BufferUINT8ArrayR buf;
buf = BufferUINT8ExternalArray_Create(arr, ARRSIZE);
// 緩沖區前面放入55
BufferUINT8_FrontIn((BufferUINT8)buf,55);
// 現在緩沖區內元素為[ 55 ]

示例程序

這里已隱去不重要的代碼:

#include 
#include "BufferExternalArrayR.h"
#include "BufferExternalArray.h"
#include "BufferMallocArray.h"

#pragma push
#pragma DATA_SEG __RPAGE_SEG PAGED_RAM
static uint8_t PagedArray[300];
#pragma pop
static uint8_t nonPagedArray[50];

static void BufferTest(BufferUINT8 buf){
 int i;
 printf("sizeof buffer:%u
FrontIn: 0 to 9
BackOut: ",BufferUINT8_getCapacity(buf));
 for(i = 0; i < 10; i++)
 ? ?BufferUINT8_FrontIn(buf,i);
 ?for(i = 0; i < 10; i++)
 ? ?printf(" %u",BufferUINT8_BackOut(buf));
 ?printf("
");
}
void main(void) {
 ?BufferUINT8 buf1,buf2,buf3;
 ?buf1 = BufferUINT8ExternalArrayR_Create(PagedArray,sizeof(PagedArray));
 ?buf2 = BufferUINT8ExternalArray_Create(nonPagedArray,sizeof(nonPagedArray));
 ?buf3 = BufferUINT8MallocArray_Create(40);
 ?printf("buf1(BufferExternalArrayR) Test:
");
 ?BufferTest(buf1);
 ?printf("buf2(BufferExternalArray) Test:
");
 ?BufferTest(buf2);
 ?printf("buf3(BufferMallocArray) Test:
");
 ?BufferTest(buf3);
 ?for(;;) {
  } 
}

a111f216-d246-11ed-bfe3-dac502259ad0.png

可以看到,上例中BufferTest并不知道傳遞給他的BufferUINT8的具體實現,它只需要知道這個實例實現了BufferUINT8的方法就可以正確地對其進行操作,從而實現了解耦。

另,上例中的BufferUINT8_getCapacity其實是因為我在Buffer模塊的頭文件中用宏的方式給Container_getCapacity起了別名,這樣用起來就更順手了對吧。

審核編輯:湯梓紅

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 模塊
    +關注

    關注

    7

    文章

    2726

    瀏覽量

    47612
  • 緩沖區
    +關注

    關注

    0

    文章

    33

    瀏覽量

    9142
  • C語言
    +關注

    關注

    180

    文章

    7614

    瀏覽量

    137249
  • 面向對象
    +關注

    關注

    0

    文章

    64

    瀏覽量

    9994

原文標題:循環隊列C語言面向對象實現

文章出處:【微信號:技術讓夢想更偉大,微信公眾號:技術讓夢想更偉大】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    C語言實現面向對象的方式 C++中的class的運行原理

    這里主要介紹下在C語言中是如何實現面向對象。知道了C語言實
    發表于 10-21 09:00 ?1151次閱讀

    嵌入式C語言面向對象編程---多態

    前兩篇文章主要講述了 C 語言面向對象編程– 封裝和繼承。本篇文章繼續來討論一下,如何使用 C 語言實現
    發表于 10-31 14:41 ?1028次閱讀

    單片機C語言 -- 基于結構體的面向對象編程技巧

    :系統初始化后,進入主循環,通過結構體調用system文件的函數。2、結構體類型定義定義1個變量與2個函數指針。單片機C語言面向對象編程,
    發表于 02-04 21:48

    如何用C語言實現面向對象編程

    1 用C語言實現面向對象編程GOF的《設計模式》一書的副標題叫做“可復用面向對象軟件的基礎”,從
    發表于 07-12 07:24

    c語言實現面向對象編程 精選資料分享

    差異。在語法上,C語言支持的oop(面向對象)機制比較薄弱,但完全可以使用c語言寫出
    發表于 09-02 07:46

    面向對象編程語言的特點

    工業控制系統的PLC程序中也可以采用這種設計思想,雖然我們無法實現面向對象的很多優秀特點如“繼承”,甚至于它根本就不具備面向對象編程
    發表于 09-08 07:44

    C++語言和面向對象程序設計教程

    C++語言和面向對象程序設計代表了旨在使計算機問題解更加符合人的思維活動,是軟件開發方法的一場革命;面向對象建模和
    發表于 03-02 08:00 ?6次下載

    為什么要用C語言實現面向對象

    對象的編程語言,但面向對象的概念是在C語言階段就有了,而且應用到了很多地方,比如某些操作系統內核
    的頭像 發表于 11-05 18:05 ?1732次閱讀
    為什么要用<b class='flag-5'>C</b><b class='flag-5'>語言實現</b><b class='flag-5'>面向</b><b class='flag-5'>對象</b>

    如何用C語言實現面向對象編程OOP?

    解釋區分一下C語言和OOP我們經常說C語言面向過程的,而C++是
    的頭像 發表于 12-18 16:18 ?2485次閱讀

    C語言是如何實現面向對象

    C++是 面向對象 的編程語言,但面向對象的概念是在C
    的頭像 發表于 12-24 17:08 ?2w次閱讀
    <b class='flag-5'>C</b><b class='flag-5'>語言</b>是如何<b class='flag-5'>實現</b><b class='flag-5'>面向</b><b class='flag-5'>對象</b>的

    為什么要用C語言實現面向對象

    對象的編程語言,但面向對象的概念是在C語言階段就有了,而且應用到了很多地方,比如某些操作系統內核
    的頭像 發表于 06-04 17:44 ?2352次閱讀
    為什么要用<b class='flag-5'>C</b><b class='flag-5'>語言實現</b><b class='flag-5'>面向</b><b class='flag-5'>對象</b>呢

    為什么要用C語言實現面向對象呢?

    對象的編程語言,但面向對象的概念是在C語言階段就有了,而且應用到了很多地方,比如某些操作系統內核
    的頭像 發表于 06-12 17:55 ?1744次閱讀
    為什么要用<b class='flag-5'>C</b><b class='flag-5'>語言實現</b><b class='flag-5'>面向</b><b class='flag-5'>對象</b>呢?

    嵌入式C語言面向對象編程應用及優勢

    既然面向對象是一種編程思想,而編程語言只是一種工具,那么,思想與工具之間就不存在一種強耦合的關系,C++可以面向
    發表于 11-10 12:00 ?1814次閱讀
    嵌入式<b class='flag-5'>C</b><b class='flag-5'>語言</b><b class='flag-5'>面向</b><b class='flag-5'>對象</b>編程應用及優勢

    C語言是怎么面向對象編程

    在嵌入式開發中,C/C++語言是使用最普及的,在C++11版本之前,它們的語法是比較相似的,只不過C++提供了
    的頭像 發表于 02-14 13:57 ?1705次閱讀
    <b class='flag-5'>C</b><b class='flag-5'>語言</b>是怎么<b class='flag-5'>面向</b><b class='flag-5'>對象</b>編程

    淺談C語言面向對象編程思想

    C語言是一種面向過程的語言,但是也可以用結構體和函數指針來模擬面向對象的特性,比如封裝、繼承和多
    發表于 11-02 12:27 ?1151次閱讀
    主站蜘蛛池模板: 亚洲精品第一| 免费的黄色的视频| 亚洲日本一区二区三区在线不卡| 午夜cao| 天天干一干| 国产美女视频一区二区三区| 黄色三级在线观看| 国产一二三区精品| 欧美69视频在线| 久久精品视频5| 你懂的在线免费观看| 免费人成年短视频在线观看免费网站 | 天天se天天cao综合网蜜芽| fc2 ppv sss级素人美女| 午夜高清免费在线观看| 欧美天天色| 天堂在线最新版在线www| 免费观看片| 日处女穴| 黄视频在线免费看| 日本aaaaa| 亚洲精品成人在线| 亚欧洲乱码专区视频| 视频在线视频免费观看| 亚洲情欲网| 亚洲狠狠婷婷综合久久久久图片| 色香蕉在线观看| 四虎影视永久在线精品免费播放| 日韩欧美一级| 七月丁香八月婷婷综合激情| 久久精品免费观看视频| 亚洲天天综合| yyy6080韩国三级理论| 人人添人人澡人人澡人人人爽| 亚洲国内精品| 欧美成人观看免费全部完小说| 成人欧美一区二区三区视频不卡| 天堂在线最新版www中文| 免费免播放器在线视频观看| 91视频www| 伊人久久大香线蕉综合电影|