日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

C语言面向对象编程(一):封装与继承

發布時間:2025/3/12 编程问答 15 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C语言面向对象编程(一):封装与继承 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
最近在用 C 做項目,之前用慣了 C++ ,轉回頭來用C 還真有點不適應。 C++ 語言中自帶面向對象支持,如封裝、繼承、多態等面向對象的基本特征。 C 原本是面向過程的語言,自身沒有內建這些特性,但我們還是可以利用 C 語言本身已有的特性來實現面向對象的一些基本特征。接下來我們就一一來細說封裝、繼承、多態、純虛類等面向對象特性在 C 語言中如何實現,并且給出實例。

? ? 這篇文章中我們先說封裝和繼承。

? ? 先來看封裝。

? ? 所謂封裝,通俗地說,就是一個姑娘化了妝,只給你看她想讓你看的那一面,至于里面是否刮了骨、墊了東西,不給你看。說到封裝就得說隱藏,這是對兄弟概念;其實我理解隱藏是更深的封裝,完全不給你看見,而封裝可能是猶抱琵琶半遮面。封裝在 C++ 語言中有 protected 、 private 關鍵字在語言層面上支持,而 C 語言中沒有這些。 C 有結構體( struct ),其實可以實現封裝和隱藏。

? ? 在 QT 中,為了更好的隱藏一個類的具體實現,一般是一個公開頭文件、一個私有頭文件,私有頭文件中定義實現的內部細節,公開頭文件中定義開放給客戶程序員的接口和公共數據。看看 QObject (qobject.h ),對應有一個 QObjectPrivate (qobject_p.h ) ,其他的也類似。而代碼框架如下:

[cpp] view plaincopy print?
  • QObject{??
  • public:??
  • ????xxx??
  • ????xxx??
  • private:??
  • ????QObjectPrivate?*?priv;??
  • };??
  • QObject{ public:xxxxxx private:QObjectPrivate * priv; };? ? 我們在 C 語言中完全可以用同樣的方法來實現封裝和隱藏,只不過是放在結構體中而已。代碼框架如下:

    [cpp] view plaincopy print?
  • struct?st_abc_private;??
  • struct?st_abc?{??
  • ????int?a;??
  • ????xxx;??
  • ????void?(*xyz_func)(struct?st_abc*);??
  • ??
  • ????struct?st_abc_private?*?priv;??
  • };??
  • struct st_abc_private; struct st_abc {int a;xxx;void (*xyz_func)(struct st_abc*);struct st_abc_private * priv; };? ? 上面的代碼,我們只前向聲明結構體 struct st_abc_private ,沒人知道它里面具體是什么東西。假如 struct st_abc 對應的頭文件是 abc.h ,那么把 st_abc_private 的聲明放在 abc_p.h 中,abc.c 文件包含 abc_p.h ,那么在實現 struct st_abc 的函數指針 xyz_func 時如何使用 struct st_abc_private ,客戶程序員根本無須知道。

    ? ? 這樣做的好處是顯而易見的,除了預定義好的接口,客戶程序員完全不需要知道實現細節,即便實現經過重構完全重來,客戶程序員也不需要關注,甚至相應的模塊連重新編譯都不要——因為 abc.h 自始至終都沒變過。

    ? ? 上面代碼有個問題,客戶程序員如何得到 struct st_abc 的一個實例,他不知道 struct st_abc_private 如何實現的呀。 C 中沒有構造函數,只好我們自己提供了:我們可以在 abc.h 中聲明一個類似構造函數的函數來生成 struct st_abc 的實例,名字就叫作 new_abc() ,函數原型如下:

    [cpp] view plaincopy print?
  • struct?st_abc?*?new_abc();??
  • struct st_abc * new_abc();? ? 至于實現,我們放在 abc.c 中,客戶程序員不需要知道。相應的,還有個類似析構函數的函數,原型如下:

    [cpp] view plaincopy print?
  • void?delete_abc(struct?st_abc?*);??
  • void delete_abc(struct st_abc *);
    ? ? 到現在為止,封裝和隱藏就實現了,而且很徹底。接下來看繼承。

    ? ? 什么是繼承?在面向對象層面上不講了,只說語法層面。語法層面上講,繼承就是派生類擁有父類的數據、方法,又添了點自己的東西,所謂子承父業,發揚光大。在 C 語言中可以用結構體的包含來實現繼承關系。代碼框架如下:

    [cpp] view plaincopy print?
  • struct?st_base{??
  • ????xxx;??
  • };??
  • ??
  • struct?st_derived{??
  • ????struct?sb_base?base;??
  • ????yyy;??
  • };??
  • struct st_base{xxx; };struct st_derived{struct sb_base base;yyy; }; ? ? 代碼上就是這么簡單,不過有一點要注意:第一點就是派生類(結構體)中一定要把父類類型的成員放在第一個。

    ? ? 繼承在語法層面上看,有數據成員、函數,數據成員通過上面的方法自動就“繼承”了,至于函數,在結構體表示為函數指針,其實也是一個數據成員,是個指針而已,也會自動“繼承”。之所以還要在這里列出來說明,是因為 C++ 中有一個很重要的概念:重載。要在 C 中完整實現有點兒麻煩。

    ? ? 重載,我們常說的重載大概有三種含義:

    • 其一,函數重載,指函數名字一樣,參數個數、類型不一樣的函數聲明和實現。由于 C 編譯器的緣故,不支持。不過這個影響不大。
    • 其二,重定義或者說覆蓋,指派生類中定義與基類簽名一樣(名字、返回值、參數完全一樣)的非虛函數,這樣派生類的中的函數會覆蓋基類的同簽名函數,通過成員操作符訪問時無法訪問基類的同簽名函數。
    • 其三,虛函數重寫,指在派生類中實現基類定義的虛函數或純虛函數。虛函數是實現多態的關鍵,可以在結構體中使用函數指針來表達,但要完全實現,也很麻煩。

    ? ? 我們平常在交流時通常不明確區分上面三種類型的重載,這里出于習慣,也不作區分。
    ? ? 好了,第一篇就到這里,有時間會往下續。

    總結

    以上是生活随笔為你收集整理的C语言面向对象编程(一):封装与继承的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。