1、 概述
c語言是一種面向過程的程式語言,而c++是在c語言基礎上衍生來了的物件導向的語言,實際上,很多c++實現的底層是用c語言實現的,如在visual c++中的inte***ce其實就是struct,查詢inte***ce的定義,你可以發現有這樣的巨集定義:
#ifndef inte***ce
#define inte***ce struct
#endif
c++在語言級別上新增了很多新機制(繼承,多型等),而在c語言中,我們也可以使用這樣的機制,前提是我們不得不自己實現。
本文介紹了用c語言實現封裝,繼承和多型的方法。
2、 基本知識
在正式介紹c語言實現封裝,繼承和多型事前,先介紹一下c語言中的幾個概念和語法。
(1) 結構體
在c語言中,常把乙個物件用結構體進行封裝,這樣便於對物件進行操作,比如:
strcut point;
結構體可以巢狀。因而可以把乙個結構體當成另乙個結構體的成員,如:
struct circle ;
該結構體與以下定義完全一樣(包括記憶體布置都一樣):
struct circle ;
(2) 函式指標
函式指標是指標的一種,它指向函式的首位址(函式的函式名即為函式的首位址),可以通過函式指標來呼叫函式。
如函式:
int func(int a, int n);
可以這樣宣告函式指標:
int (*pfunc)(int a, int n);
這樣使用:
pfunc = func;
(*pfunc)(a, n);【或者pfunc(a, n)】
可以用typedef定義乙個函式指標型別,如:
typdef int (*func)(int a, int n)
可以這樣使用:
int cal_a(func fptr, int a, int n)
//實現體
(3) extern與static
extern和static是c語言中的兩個修飾符,extern可用於修飾函式或者變數,表示該變數或者函式在其他檔案中進行了定義;static也可用於修飾函式或者變數,表示該函式或者變數只能在該檔案中使用。可利用它們對資料或者函式進行隱藏或者限制訪問許可權。
3、 封裝
在c語言中,可以用結構+函式指標來模擬類的實現,而用這種結構定義的變數就是物件。
封裝的主要含義是隱藏內部的行為和資訊,使用者只用看到對外提供的介面和公開的資訊。有兩種方法實現封裝:
(1) 利用c語言語法。在標頭檔案中宣告,在c檔案中真正定義它。
這樣可以隱藏內部資訊,因為外部不知道物件所佔記憶體的大小,所以不能靜態的建立該類的物件,只能呼叫類提供的建立函式才能建立。這種方法的缺陷是不支援繼承,因為子類中得不到任何關於父類的資訊。如:
//標頭檔案:point.h
#ifndef point_h
#define point_h
struct point;
typedef struct point point;
point * new_point(); //newer a point object
void free_point(point *point_);// free the allocated space
#endif
//c檔案:point.c
#include」point.h」
strcut point
;point * new_point()
void free_point(point *point_)
(2) 把私有資料資訊放在乙個不透明的priv變數或者結構體中。只有類的實現**才知道priv或者結構體的真正定義。如:
#ifndef point _h
#define point_h
typedef struct point point;
typedef struct pointprivate pointprivate;
strcut point
;int get_x(point *point_);
int get_y(point *point_);
point * new_point(); //newer a point object
void free_point(point *point_);// free the allocated space
#endif
//c檔案:point.c
#include」point.h」
struct pointprivate
int get_x(point *point_)
int get_y(point *point_)
//others…..
4、 繼承
在c語言中,可以利用「結構在記憶體中的布局與結構的宣告具有一致的順序」這一事實實現繼承。
比如我們要設計乙個作圖工具,其中可能涉及到的物件有point(點),circle(圓),由於圓是由點組成的,所有可以看成circle繼承自point。另外,point和circle都需要空間申請,空間釋放等操作,所有他們有共同的基類base。
//記憶體管理類new.h
#ifndef new_h
#define new_h
void * new (const void * class, ...);
void delete (void * item);
void draw (const void * self);
#endif
//記憶體管理類的c檔案:new.c
#include 「new.h」
#include 「base.h」
void * new (const void * _base, ...)
return p;
}void delete (void * self)
void draw (const void * self)
//基類:base.h
#ifndef base_h
#define base_h
struct base
;#endif
//point標頭檔案(對外提供的介面):point.h
#ifndef point_h
#define point_h
extern const void * point; /* 使用方法:new (point, x, y); */
#endif
//point內部標頭檔案(外面看不到):point.r
#ifndef point_r
#define point_r
struct point
;#endif
//point的c檔案:point.c
#include 「point.h」
#include 「new.h」
#include 「point.h」
#include 「point.r」
static void point_draw (const void * _self)
static const struct base _point = ;
const void * point = & _point;
//測試程式:main.c
#include 「point.h」
#include 「new.h」
int main (int argc, char ** argv)
同樣,circle要繼承point,則可以這樣:
struct circle
;
5、 多型
可以是用c語言中的萬能指標void* 實現多型,接上面的例子:
//測試main.c
void * p = new(point, 1, 2);
void * pp = new(circle, 1, 2);
draw(p); //draw函式實現了多型
draw(pp);
delete(p);
delete(pp);
6、 總結
c語言能夠模擬實現物件導向語言具有的特性,包括:多型,繼承,封裝等,現在很多開源軟體都了用c語言實現了這幾個特性,包括大型開源資料庫系統postgresql,可移植的c語言物件導向框架gobject,無線二進位制執行環境brew。採用c語言實現多型,繼承,封裝,能夠讓軟體有更好的可讀性,可擴充套件性。
7、 參考資料
(1) 《c語言中extern和static用法》:
(2) 《三、使用gobject——私有成員和靜態變數》:
(3) 《技巧:用 c 語言實現程式的多型性》:
(4) 書籍《object-oriented programming with ansi-c》
c 封裝,繼承,多型
一 封裝 封裝是實現物件導向程式設計的第一步,封裝就是將資料或函式等集合在乙個個的單元中 我們稱之為類 被封裝的物件通常被稱為抽象資料型別。物件導向程式設計中一般以類作為資料封裝的基本單位。類將資料和運算元據的方法結合成乙個單位。在設計類時,不希望直接訪問類中的資料,而是希望通過方法來訪問資料。如此...
C 封裝 繼承 多型
物件導向的三個基本特徵 物件導向的三個基本特徵是 封裝 繼承 多型。其中,封裝可以隱藏實現細節,使得 模組化 繼承可以擴充套件已存在的 模組 類 它們的目的都是為了 重用。而多型則是為了實現另乙個目的 介面重用!封裝 什麼是封裝?封裝可以隱藏實現細節,使得 模組化 封裝是把過程和資料報圍起來,對資料...
c 封裝,繼承,多型
c 中可使用類來達到資料封裝的效果,這樣可以使資料與方法封裝成單一元素,以便於通過方法訪問資料。除此之外,還可以控制資料的訪問方式。在物件導向程式設計中,大多數都是以類作為資料封裝的基本單位。類將資料和運算元據的方法結合成乙個單位。設計類時,不希望直接訪問類中的資料,而是希望通過方法來訪問資料。這樣...