嵌入式C語言高級編程:OOP封裝、TDD測試與防御性編程實踐

一、面向對象編程(OOP)

盡管 C 語言并非面向對象編程語言,但借助一些編程技巧,也能實現面向對象編程(OOP)的核心特性,如封裝、繼承和多態。

image.png

1.1 封裝

封裝是把數據和操作數據的函數捆綁在一起,對外部隱藏內部實現細節。在嵌入式 C 語言中,可通過結構體和函數指針來實現封裝。

#include <stdio.h>// 定義一個LED結構體
typedef struct?{int?pin;void?(*turnOn)(struct LED*);void?(*turnOff)(struct LED*);
} LED;// 實現LED開啟函數
void ledTurnOn(LED* led){printf("LED on pin %d is turned on.\n", led->pin);
}// 實現LED關閉函數
void ledTurnOff(LED* led){printf("LED on pin %d is turned off.\n", led->pin);
}// 初始化LED
void ledInit(LED* led,?int?pin){led->pin = pin;led->turnOn = ledTurnOn;led->turnOff = ledTurnOff;
}int main(void){LED myLed;ledInit(&myLed,?13);myLed.turnOn(&myLed);myLed.turnOff(&myLed);return0;
}

844d340c655e33f2b963e0810e02de27.png

LED結構體封裝了pin數據和turnOn、turnOff函數指針。ledInit函數用于初始化LED結構體,把具體的函數賦值給函數指針。外部代碼僅能通過這些函數指針來操作LED,而無需了解內部實現細節。

1.2 繼承

繼承是指一個對象直接使用另一對象的屬性和方法。在嵌入式 C 語言中,可通過結構體嵌套實現繼承。

#include <stdio.h>// 定義一個基類結構體
typedef struct?{int?id;void?(*printInfo)(struct Base*);
} Base;// 實現基類的打印信息函數
voidbasePrintInfo(Base* base){printf("Base ID: %d\n", base->id);
}// 定義一個派生類結構體
typedef struct?{Base base;?// 繼承Base結構體char* name;
} Derived;// 實現派生類的打印信息函數
void derivedPrintInfo(Derived* derived){basePrintInfo(&derived->base);printf("Derived Name: %s\n", derived->name);
}// 初始化基類
void baseInit(Base* base,?int?id){base->id = id;base->printInfo = basePrintInfo;
}// 初始化派生類
void derivedInit(Derived* derived,?int?id,?char* name){baseInit(&derived->base, id);derived->name = name;derived->base.printInfo = (void?(*)(Base*))derivedPrintInfo;
}int main(void){Derived myDerived;derivedInit(&myDerived,?1,?"Derived Object");myDerived.base.printInfo((Base*)&myDerived);return0;
}

a4cb6b6581022271005e1da9e13d08e0.png

1.3 多態

多態是指不同對象對同一消息做出不同響應。在嵌入式 C 語言中,可通過函數指針實現多態。

#include <stdio.h>// 定義一個基類結構體
typedef struct?{void?(*operation)(struct Base*);
} Base;// 定義一個派生類1結構體
typedef struct?{Base base;
} Derived1;// 定義一個派生類2結構體
typedef struct?{Base base;
} Derived2;// 派生類1的操作函數
void derived1Operation(Base* base){printf("Derived1 operation.\n");
}// 派生類2的操作函數
void derived2Operation(Base* base){printf("Derived2 operation.\n");
}// 初始化派生類1
void derived1Init(Derived1* derived1){derived1->base.operation = derived1Operation;
}// 初始化派生類2
void derived2Init(Derived2* derived2){derived2->base.operation = derived2Operation;
}// 執行操作
void performOperation(Base* base){base->operation(base);
}int main(void){Derived1 myDerived1;Derived2 myDerived2;derived1Init(&myDerived1);derived2Init(&myDerived2);performOperation((Base*)&myDerived1);performOperation((Base*)&myDerived2);return0;
}

f74aabdc489581d0b018da4afe783746.png

Base結構體包含一個函數指針operation。Derived1和Derived2結構體繼承了Base結構體,并分別實現了自己的operation函數。performOperation函數接收一個Base指針,依據具體對象調用相應的operation函數,從而實現了多態。

二、測試驅動開發(TDD)

測試驅動開發(Test-Driven Development,TDD)是一種軟件開發方法論,它強調在編寫實際功能代碼之前先編寫測試代碼。

TDD 的核心流程遵循 “紅 - 綠 - 重構” 循環,下面將詳細介紹其原理、流程、優勢、局限性以及示例。

點擊嵌入式C語言高級編程:OOP封裝、TDD測試與防御性編程實踐 查看全文

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/76961.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/76961.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/76961.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

藍橋杯 web 常考到的一些知識點

filter&#xff1a;filter方法創建一個新數組&#xff0c;其包含通過所提供函數實現的測試的所有元素。這個 方法不會改變原數組&#xff0c;而是返回一個新的數組。 map&#xff1a;map方法創建一個新數組&#xff0c;其結果是該數組中的每個元素都調用一個提供的函數后的 返回…

音視頻小白系統入門筆記-0

本系列筆記為博主學習李超老師課程的課堂筆記&#xff0c;僅供參閱 音視頻小白系統入門課 音視頻基礎ffmpeg原理 緒論 ffmpeg推流 ffplay/vlc拉流 使用rtmp協議 ffmpeg -i <source_path> -f flv rtmp://<rtmp_server_path> 為什么會推流失敗&#xff1f; 默認…

mysql按條件三表并聯查詢

下面為你呈現一個 MySQL 按條件三表并聯查詢的示例。假定有三個表&#xff1a;students、courses 和 enrollments&#xff0c;它們的結構和關聯如下&#xff1a; students 表&#xff1a;包含學生的基本信息&#xff0c;有 student_id 和 student_name 等字段。courses 表&…

UML之序列圖的消息

序列圖表現各參與者之間為完成某個行為而發生的交互及其時間順序&#xff0c;序列圖中的交互通過消息實現。消息是從一條生命線到另一條生命線的通信&#xff0c;它們通常是水平或傾斜向下的箭頭&#xff0c;從發送方生命線離開&#xff0c;到達接收方生命線。如果需要&#xf…

UniAD:自動駕駛的統一架構 - 創新與挑戰并存

引言 自動駕駛技術正經歷一場架構革命。傳統上&#xff0c;自動駕駛系統采用模塊化設計&#xff0c;將感知、預測和規劃分離為獨立組件。而上海人工智能實驗室的OpenDriveLab團隊提出的UniAD&#xff08;Unified Autonomous Driving&#xff09;則嘗試將這些任務整合到一個統一…

如何寫好合同管理系統需求分析

引言 在當今企業數字化轉型的浪潮中&#xff0c;合同管理系統作為企業法律合規和商業運營的重要支撐工具&#xff0c;其需求分析的準確性和完整性直接關系到系統建設的成敗。本文基于Volere需求過程方法論&#xff0c;結合江鈴汽車集團合同管理系統需求規格說明書實踐案例&…

libevent服務器附帶qt界面開發(附帶源碼)

本章是入門章節&#xff0c;講解如何實現一個附帶界面的服務器&#xff0c;后續會完善與優化 使用qt編譯libevent源碼演示視頻qt的一些知識 1.主要功能有登錄界面 2.基于libevent實現的服務器的業務功能 使用qt編譯libevent 下載這個&#xff0c;其他版本也可以 主要是github上…

八、自動化函數

1.元素的定位 web自動化測試的操作核心是能夠找到頁面對應的元素&#xff0c;然后才能對元素進行具體的操作。 常見的元素定位方式非常多&#xff0c;如id,classname,tagname,xpath,cssSelector 常用的主要由cssSelector和xpath 1.1 cssSelector選擇器 選擇器的功能&#x…

Web三漏洞學習(其二:sql注入)

靶場&#xff1a;NSSCTF 、云曦歷年考核題 二、sql注入 NSSCTF 【SWPUCTF 2021 新生賽】easy_sql 這題雖然之前做過&#xff0c;但為了學習sql&#xff0c;整理一下就再寫一次 打開以后是杰哥的界面 注意到html網頁標題的名稱是 “參數是wllm” 那就傳參數值試一試 首先判…

單片機非耦合業務邏輯框架

在小型單片機項目開發初期&#xff0c;由于業務邏輯相對簡單&#xff0c;我們往往較少關注程序架構層面的設計。 然而隨著項目經驗的積累&#xff0c;開發者會逐漸意識到模塊間的耦合問題&#xff1a;當功能迭代時&#xff0c;一處修改可能引發連鎖反應。 此時&#xff0c;構…

Zookeeper三臺服務器三節點集群部署(docker-compose方式)

1. 準備工作 - 服務器:3 臺服務器,IP 地址分別為 `10.10.10.11`、`10.10.10.12`、`10.10.10.13`。 - 安裝 Docker:確保每臺服務器已安裝 Docker 和 Docker Compose。 - 網絡通信:確保三臺服務器之間可以通過 IP 地址互相訪問,并開放以下端口: - `2181`:Zookeeper 客戶…

Mac關閉sip方法

Mac關閉sip方法 導航 文章目錄 Mac關閉sip方法導航完整操作流程圖詳細步驟 完整操作流程圖 這東西是我在網上搬運下來的&#xff0c;但是我在為業務實操過程中&#xff0c;根據實操情況還是有新的注意點的 詳細步驟 1.在「關于本機」-「系統報告」-「軟件」;查看SIP是否開啟…

C++| 深入剖析std::list底層實現:鏈表結構與內存管理機制

引言 std::list的底層實現基于雙向鏈表&#xff0c;其設計哲學與std::vector截然不同。本文將深入探討其節點結構、內存分配策略及迭代器實現原理&#xff0c;揭示鏈表的性能優勢和潛在代價。 1. 底層數據結構&#xff1a;雙向鏈表 每個std::list節點包含&#xff1a; 數據域…

漢諾塔問題——用貪心算法解決

目錄 一&#xff1a;起源 二&#xff1a;問題描述 三&#xff1a;規律 三&#xff1a;解決方案 遞歸算法 四&#xff1a;代碼實現 復雜度分析 一&#xff1a;起源 漢諾塔&#xff08;Tower of Hanoi&#xff09;問題起源于一個印度的古老傳說。在世界中心貝拿勒斯&#…

【Python】Python 100題 分類入門練習題 - 新手友好

Python 100題 分類入門練習題 - 新手友好篇 - 整合篇 一、數學問題題目1&#xff1a;組合數字題目2&#xff1a;利潤計算題目3&#xff1a;完全平方數題目4&#xff1a;日期天數計算題目11&#xff1a;兔子繁殖問題題目18&#xff1a;數列求和題目19&#xff1a;完數判斷題目21…

【linux】--- 進程概念

進程概念 1.認識馮諾依曼結構2. 操作系統&#xff08;Operator system)2.1 概念2.2 設計OS的目的2.3 理解操作系統2.4 如何理解管理2.5 理解系統調用和庫函數 3. 進程3.1 基本概念和基本操作3.1.1 描述進程 - PCB3.1.2 task_struct3.1.3 查看進程 3.2 進程狀態3.2.1 運行&&…

算法堆排序記錄

【算法】排序算法之堆排序 - 知乎 應用場景&#xff1a;獲取第n個大或者小的數 操作步驟&#xff1a; 1、將數組構造成堆 2、調整根節點為最大堆 ->倒序對每個根節點執行最大化 ->根節點最大化過程中如果發生交換&#xff0c;需要保證子節點也為最大堆&#xff08;執行…

STM32 模塊化開發實戰指南:系列介紹

本文是《STM32 模塊化開發實戰指南》系列的導讀篇,旨在介紹整個系列的寫作目的、適用讀者、技術路徑和每一篇的主題規劃。適合從事 STM32、裸機或 RTOS 嵌入式開發的個人開發者、初創工程師或企業項目團隊。 為什么要寫這個系列? 在嵌入式開發中,很多人剛開始都是從點亮一個…

【眼底輔助診斷開放平臺】項目筆記

這是一個標題 任務一前端頁面開發&#xff1a;后端接口配置&#xff1a; 任務二自行部署接入服務 日志修改樣式和解析MD文檔接入服務 Note前端登陸不進去/更改后端api接口304 Not Modifiedlogin.cache.jsonERR_CONNECTION_TIMED_OUT跨域一般提交格式proxy.ts src/coponents 目錄…

【后端開發】Spring MVC-計算器、用戶登錄、留言板

文章目錄 前后端分離設計接口設計思路項目問題解決思路 計算器需求分析接口定義前端頁面代碼服務器代碼 用戶登錄需求分析接口定義用戶登錄校驗接口查詢登錄用戶接口 前端頁面代碼用戶登錄校驗查詢登錄用戶 服務器代碼前后端交互 留言版需求分析接口定義獲取全部留言發布留言前…