www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當(dāng)前位置:首頁(yè) > 公眾號(hào)精選 > 嵌入式微處理器
[導(dǎo)讀]C和C++的最大區(qū)別便是,C++有類(lèi),C沒(méi)有類(lèi)的概念。單單這一個(gè)類(lèi)使得C缺失很多的東西。好在C有結(jié)構(gòu)體,勉強(qiáng)可以當(dāng)0.1個(gè)類(lèi)來(lái)使用。

微信公眾號(hào):二進(jìn)制人生
專(zhuān)注于嵌入式linux開(kāi)發(fā)。

目錄

前言1、繼承2、封裝偽構(gòu)造函數(shù)3、多態(tài)

前言

我們都知道C語(yǔ)言是一門(mén)過(guò)程性語(yǔ)言,所謂過(guò)程性就是在解決問(wèn)題時(shí),將問(wèn)題按步驟分解。

例如,做菜的時(shí)候,先點(diǎn)火,再倒油,接著下菜翻炒,最后加鹽和醬油。但有時(shí)候借鑒面向?qū)ο?/a>的思想來(lái)組織代碼,邏輯層次會(huì)更加清晰。

C和C++的最大區(qū)別便是,C++有類(lèi),C沒(méi)有類(lèi)的概念。單單這一個(gè)類(lèi)使得C缺失很多的東西。好在C有結(jié)構(gòu)體,勉強(qiáng)可以當(dāng)0.1個(gè)類(lèi)來(lái)使用。

眾所周知,類(lèi)有三大特性:封裝、繼承、多態(tài)。我們來(lái)看看C語(yǔ)言如何借鑒類(lèi)的三大特性來(lái)更好的組織代碼。

1、繼承

C語(yǔ)言沒(méi)有嚴(yán)格意義上的繼承,可以借助結(jié)構(gòu)體嵌套實(shí)現(xiàn)類(lèi)似于繼承的形式,但始終不盡人意。

struct?parent
{

????int?a;
};
struct?son
{

????struct?parent?p;//兒子繼承父親
????int?b;
};

C++的類(lèi)可以實(shí)現(xiàn)成員的訪問(wèn)控制,例如將變量b聲明成private,那么外部就無(wú)法訪問(wèn)。但C的結(jié)構(gòu)體做不到。

在C++里頭,父親的私有成員,兒子是無(wú)法訪問(wèn)的。結(jié)構(gòu)體嵌套也做不到。因?yàn)榻Y(jié)構(gòu)體根本就沒(méi)有訪問(wèn)控制的概念。

對(duì)于C++而言,訪問(wèn)控制實(shí)質(zhì)上是在編譯層做的,我們?nèi)耘f可以通過(guò)指針來(lái)間接訪問(wèn)。

例如:

class?Base{
public:
???int?a;
private:
???int?b;
};

盡管b被聲明成私有,但我們?nèi)耘f有辦法訪問(wèn)它(借助指針繞過(guò)語(yǔ)法檢查):

Base?t;
int?*p?=?&t.a;
cout?<1]?<endl;

2、封裝

封裝就是把數(shù)據(jù)和方法打包到一個(gè)類(lèi)里面。C++的實(shí)現(xiàn)大致如下:

class?類(lèi)名
{

public:
????公有方法1
????公有方法2
????……
????公有數(shù)據(jù)1
????……
private:
????私有方法1
????私有方法2
????……
????私有數(shù)據(jù)1
????……
};

這樣做的好處是顯而易見(jiàn)的。一個(gè)類(lèi)實(shí)現(xiàn)了一個(gè)小模塊,使得代碼結(jié)構(gòu)比較清晰。對(duì)外接口和數(shù)據(jù)定義成public,允許調(diào)用者直接訪問(wèn)。內(nèi)部接口和數(shù)據(jù)定義成private,外部不可見(jiàn)。

在 QT 中,為了更好的隱藏一個(gè)類(lèi)的具體實(shí)現(xiàn),一般是一個(gè)公開(kāi)頭文件、一個(gè)私有頭文件,私有頭文件中定義實(shí)現(xiàn)的內(nèi)部細(xì)節(jié),公開(kāi)頭文件中定義開(kāi)放給客戶程序員的接口和公共數(shù)據(jù)。看看QObject (qobject.h),對(duì)應(yīng)有一QObjectPrivate(qobject_p.h ) ,其他的也類(lèi)似。

QObject{
public:
????xxx
????xxx
private:
????QObjectPrivate?*?priv;
};

我們可以借助C語(yǔ)言的指針和結(jié)構(gòu)體來(lái)實(shí)現(xiàn)方法和數(shù)據(jù)的封裝?;究蚣苋缦拢?/p>

struct?結(jié)構(gòu)體名{
????數(shù)據(jù)1
????數(shù)據(jù)2;
????……
????方法1:
????方法2;
????……
}

在結(jié)構(gòu)體里定義成員變量很容易,直接int a;
在結(jié)構(gòu)體里定義成員函數(shù)要使用函數(shù)指針,比如:

int?(*func)(void?*)

所以,我們把上面的框架具體化就是:

struct?manager{
????int?data1;
????int?data2;
????int?(*operation1)(struct?manager*);
????int?(*operation2)(struct?manager*);
};

實(shí)際上,C++的成員函數(shù)也是通過(guò)函數(shù)指針的形式來(lái)實(shí)現(xiàn),本質(zhì)上是一致的。我們都知道類(lèi)的成員函數(shù)和類(lèi)的成員變量是分開(kāi)存儲(chǔ)的,同一個(gè)類(lèi)的所有對(duì)象,成員函數(shù)只需要占據(jù)一份地址空間。

在定義結(jié)構(gòu)體之后,函數(shù)指針并沒(méi)有賦值,一般我們會(huì)定義一個(gè)結(jié)構(gòu)體初始化函數(shù)來(lái)初始化結(jié)構(gòu)體成員,這有點(diǎn)類(lèi)似于類(lèi)的構(gòu)造函數(shù),但類(lèi)的構(gòu)造函數(shù)在創(chuàng)建對(duì)象時(shí)自動(dòng)調(diào)用,而我們這個(gè)結(jié)構(gòu)體初始化函數(shù)只能自己手動(dòng)調(diào)用了。

同樣的,對(duì)標(biāo)C++的析構(gòu)函數(shù),我們?cè)贑語(yǔ)言里頭有一個(gè)去初始化的函數(shù)來(lái)完成模塊的去初始化,這種思想不就是一樣的嗎?

static?int?operation1(struct?manager?*manager_ptr)
{
????……
}
static?int?operation2(struct?manager?*manager_ptr)
{
????……
}

偽構(gòu)造函數(shù)

注意,我們把兩個(gè)operation函數(shù)定義成了static,這樣子文件之外的函數(shù)就不能調(diào)用它,只能通過(guò)manager結(jié)構(gòu)體來(lái)調(diào)用。是不是感覺(jué)有點(diǎn)封裝的意味。

void?init_manager(struct?manager*?manager_ptr)
{
????manager_ptr->operation1?=?operation1;
????manager_ptr->operation2?=?operation2;
????manager_ptr->data1?=?0;
????manager_ptr->data2?=?0;
}

去初始化函數(shù)我就不寫(xiě)了。

如果operation函數(shù)在外面的文件定義,則可以作為init_manager函數(shù)的參數(shù)傳入,這種場(chǎng)景也非常常見(jiàn)。我實(shí)現(xiàn)了模塊A,該模塊的operation1函數(shù)處理數(shù)據(jù)并輸出一些結(jié)果。但是我并不知道使用該模塊的人想要什么格式的結(jié)果,比如有一些人想要json格式的結(jié)果,有些人想要xml格式的結(jié)果。我不能幫他們一一實(shí)現(xiàn)一個(gè)方法,我干脆叫你們統(tǒng)一按照我指定的函數(shù)模板,實(shí)現(xiàn)一個(gè)處理函數(shù),完了你們調(diào)用結(jié)構(gòu)體初始化函數(shù)注冊(cè)下,我會(huì)在operation1函數(shù)處理完數(shù)據(jù)后,調(diào)用你們的處理函數(shù),給你們一個(gè)滿意的結(jié)果。

為了達(dá)到上面的目的,簡(jiǎn)單修改下,我們把函數(shù)operation2定義成一種類(lèi)型,

typedef?int??(*FUN_CBK)(struct?manager *manager_ptr);

結(jié)構(gòu)體定義稍作修改:

struct?manager{
????int?data1;
????int?data2;
????int?(*operation1)(struct?manager*);
????FUN_CBK?call_back;
};

結(jié)構(gòu)體初始化函數(shù)也要做相應(yīng)的修改,增加了一個(gè)函數(shù)指針形參:

void?init_manager(struct?manager*?manager_ptr,?\
FUN_CBK?fun)
{
????manager_ptr->operation1?=?operation1;
????manager_ptr->call_back?=?fun;//用外部傳入的回調(diào)函數(shù)進(jìn)行初始化
????manager_ptr->data1?=?0;
????manager_ptr->data2?=?0;
}

通過(guò)上面的操作,我們用結(jié)構(gòu)體和函數(shù)指針完成了模塊化封裝。

我看了網(wǎng)上的博客,有些人為了特意模仿類(lèi),還用以下方式實(shí)現(xiàn)了類(lèi)似于類(lèi)的構(gòu)造函數(shù):

struct?manager?*manager_create(int?m,?int?n)
{
????struct?manager?*m?=?(struct?manager?*)\
????malloc(sizeof(struct?manager?*));
????m->data1?=?m;
????m->data2?=?n;
????m->operation1?=?operation1;
????m->operation2?=?operation2;
}

以及類(lèi)似于類(lèi)的析構(gòu)函數(shù):

void?manager_delete(struct?manager?*m_ptr)
{
????free(m_ptr);
????m_ptr?=?NULL;
}

使用示例:

struct?manager?*m_ptr?=?manager_create?(1,2);
manager_delete(m_ptr);

個(gè)人不是很喜歡這種做法,萬(wàn)一忘記調(diào)用manager_delete還有內(nèi)存泄露的風(fēng)險(xiǎn)。

結(jié)構(gòu)體歸根到底還是結(jié)構(gòu)體,不能實(shí)現(xiàn)成員對(duì)外不可見(jiàn)。而C++中將成員聲明成private之后,外部就無(wú)法訪問(wèn)了。C語(yǔ)言里想這么做,只能將該成員移出結(jié)構(gòu)體,定義為static形式。因?yàn)镃不支持在結(jié)構(gòu)體內(nèi)部定義static變量(不信,你可以自己去試下)。

為何不能在結(jié)構(gòu)體內(nèi)定義static變量,想想就知道了,static變量的地址在編譯鏈接之后是唯一且確定的,而結(jié)構(gòu)體只有在實(shí)例化時(shí)才能確定其地址,并且每個(gè)結(jié)構(gòu)體實(shí)例都有自己的地址空間。

3、多態(tài)

多態(tài)在上面的例子也有體現(xiàn)。C語(yǔ)言實(shí)現(xiàn)的多態(tài)并非是嚴(yán)格意義上的多態(tài),但是這種思想的應(yīng)用很廣泛,我們姑且叫它多態(tài)吧。你不解C++的多態(tài)也沒(méi)關(guān)系,絲毫不影響你理解下文。

linux的VFS便借鑒了這種思想。VFS(Virtual File System)是內(nèi)核提供的文件系統(tǒng)抽象層,其提供了文件系統(tǒng)的操作接口,可以隱藏底層不同文件系統(tǒng)的實(shí)現(xiàn)。

一個(gè)文件系統(tǒng)無(wú)非就是實(shí)現(xiàn)對(duì)文件、目錄的管理。針對(duì)文件VFS定義了統(tǒng)一的結(jié)構(gòu)體:

struct?file?{
????union?{
????????struct?llist_nodefu_llist;
????????struct?rcu_head?fu_rcuhead;
????}?f_u;
????struct?pathf_path;
????struct?inode*f_inode;/*?cached?value?*/
????const?struct?file_operations*f_op;
????……
};?

strcut file代表一個(gè)文件,每種文件系統(tǒng)(比如ext3,vfat)實(shí)現(xiàn)讀寫(xiě)等操作的方式都不一樣,所以將這些方法封裝成函數(shù)指針,統(tǒng)一定義在結(jié)構(gòu)體struct file_operations內(nèi)。

struct?file_operations?{
????struct?module?*owner;
????loff_t?(*llseek)?(struct?file?*,?loff_t,?int);
????ssize_t?(*read)?(struct?file?*,?char?__user?*,?size_t,?loff_t?*);
????ssize_t?(*write)?(struct?file?*,?const?char?__user?*,?size_t,?loff_t?*);
????……
};

每個(gè)文件系統(tǒng)各自完成自己的實(shí)現(xiàn)。


再寫(xiě)一個(gè)實(shí)際的例子。
定義一個(gè)人的標(biāo)準(zhǔn)接口和數(shù)據(jù)如下:

strcut?man{
????int?head;
????int?body;
????……
????void?(*say_hello)(void);//見(jiàn)面問(wèn)候的方式
};

中國(guó)人見(jiàn)面時(shí),說(shuō)你好:

void?china_say_hello(void)
{
????printf(“你好”);
}

英國(guó)人見(jiàn)面時(shí),說(shuō)hello:

void?english_say_hello(void)
{
????printf(“hello”);
}

現(xiàn)在來(lái)初始化它們各自的問(wèn)候方式:

struct?man?china{
????.say_hello?=?china_say_hello;
}
struct?man?english{
????.say_hello?=?English_say_hello;
}

英國(guó)人和中國(guó)人對(duì)外呈現(xiàn)都是struct man,其見(jiàn)面問(wèn)候的接口都是man.say_hello,但其底層實(shí)現(xiàn)卻可以不一樣。

并且我們可以在程序運(yùn)行時(shí),隨意的更改中國(guó)人的問(wèn)候方式。比如嬰兒時(shí)期,只會(huì)“哇哇”叫,長(zhǎng)大了才會(huì)說(shuō)“你好”,我們可以改變成員say_hello的值,讓其在不同時(shí)期指向不同的函數(shù),從而達(dá)到運(yùn)行時(shí)多態(tài)的目的。

其實(shí)呢,C++的多態(tài),也是通過(guò)函數(shù)指針來(lái)實(shí)現(xiàn)的,學(xué)習(xí)過(guò)C++的同學(xué)就會(huì)知道,含有虛函數(shù)的類(lèi),會(huì)維護(hù)一個(gè)虛函數(shù)表,里面存放了虛函數(shù)的地址。所以說(shuō)啊,C語(yǔ)言是C++的母語(yǔ),萬(wàn)變不離指針,指針是C語(yǔ)言的一大法寶。


-END-


本文授權(quán)轉(zhuǎn)載自二進(jìn)制人生,作者:二進(jìn)制人生




推薦閱讀



【01】長(zhǎng)見(jiàn)識(shí):你真的知道C語(yǔ)言里extern "C" 的作用嗎?
【02】硬件工程師必知的10個(gè)C語(yǔ)言技巧
【03】C語(yǔ)言如何實(shí)現(xiàn)拷貝圖片?幾行代碼即可搞定
【04】C語(yǔ)言常用的一些轉(zhuǎn)換工具函數(shù)!
【05】2020年8月程序員工資最新統(tǒng)計(jì)


免責(zé)聲明:整理文章為傳播相關(guān)技術(shù),版權(quán)歸原作者所有,如有侵權(quán),請(qǐng)聯(lián)系刪除

免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺(tái)立場(chǎng),如有問(wèn)題,請(qǐng)聯(lián)系我們,謝謝!

嵌入式ARM

掃描二維碼,關(guān)注更多精彩內(nèi)容

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專(zhuān)欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車(chē)的華為或?qū)⒋呱龈蟮莫?dú)角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

倫敦2024年8月29日 /美通社/ -- 英國(guó)汽車(chē)技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車(chē)工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車(chē)。 SODA V工具的開(kāi)發(fā)耗時(shí)1.5...

關(guān)鍵字: 汽車(chē) 人工智能 智能驅(qū)動(dòng) BSP

北京2024年8月28日 /美通社/ -- 越來(lái)越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運(yùn)行,同時(shí)企業(yè)卻面臨越來(lái)越多業(yè)務(wù)中斷的風(fēng)險(xiǎn),如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報(bào)道,騰訊和網(wǎng)易近期正在縮減他們對(duì)日本游戲市場(chǎng)的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)開(kāi)幕式在貴陽(yáng)舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語(yǔ)權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點(diǎn): 有效應(yīng)對(duì)環(huán)境變化,經(jīng)營(yíng)業(yè)績(jī)穩(wěn)中有升 落實(shí)提質(zhì)增效舉措,毛利潤(rùn)率延續(xù)升勢(shì) 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長(zhǎng) 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競(jìng)爭(zhēng)力 堅(jiān)持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競(jìng)爭(zhēng)優(yōu)勢(shì)...

關(guān)鍵字: 通信 BSP 電信運(yùn)營(yíng)商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺(tái)與中國(guó)電影電視技術(shù)學(xué)會(huì)聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會(huì)上宣布正式成立。 活動(dòng)現(xiàn)場(chǎng) NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長(zhǎng)三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會(huì)上,軟通動(dòng)力信息技術(shù)(集團(tuán))股份有限公司(以下簡(jiǎn)稱"軟通動(dòng)力")與長(zhǎng)三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉