純c語言實現(xiàn)面向?qū)ο蠓治雠c示例分享
C語言的對象化模型
面向?qū)ο蟮奶卣髦饕ǎ?BR>.封裝,隱藏內(nèi)部實現(xiàn)
.繼承,復(fù)用現(xiàn)有代碼
.多態(tài),改寫對象行為
1.1 封裝
封裝是一種信息隱蔽技術(shù),它體現(xiàn)于類的說明,是對象的重要特性。封裝使數(shù)據(jù)和加工該數(shù)據(jù)的方法(函數(shù))封裝為一個整體,以實現(xiàn)獨立性很強(qiáng)的模塊,使得用戶只能見到對象的外特性(對象能接受哪些消息,具有那些處理能力),而對象的內(nèi)特性(保存內(nèi)部狀態(tài)的私有數(shù)據(jù)和實現(xiàn)加工能力的算法)對用戶是隱蔽的。封裝的目的在于把對象的設(shè)計者和對象者的使用分開,使用者不必知曉行為實現(xiàn)的細(xì)節(jié),只須用設(shè)計者提供的消息來訪問該對象。
在C語言中,大多數(shù)函數(shù)的命名方式是動詞+名詞的形式,例如要獲取一個semaphore,會命名
成take_semaphore,重點在take這個動作上。面向?qū)ο缶幊讨袆偤孟喾?,命名為rt_sem_take,即名詞+動詞的形式,重點在名詞上,體現(xiàn)了一個對象的方法。另外對于某些方法,僅局限在對象內(nèi)部使用,它們將采用static修辭把作用范圍局限在一個文件的內(nèi)部。通過這樣的方式,把一些不想讓用戶知道的信息屏蔽在封裝里,用戶只看到了外層的接口,從而形成了面向?qū)ο笾械淖罨镜膶ο蠓庋b實現(xiàn)。
一般屬于某個類的對象會有一個統(tǒng)一的創(chuàng)建,析構(gòu)過程。
對象內(nèi)存數(shù)據(jù)塊已經(jīng)存在,需要對它進(jìn)行初始化 – rt_sem_init;對象內(nèi)存數(shù)據(jù)塊還未分配,需要創(chuàng)建并初始化 – rt_sem_create。可以這么認(rèn)為,對象的創(chuàng)建(create)是以對象的初始化(init)為基礎(chǔ)的,創(chuàng)建動作相比較而言多了個內(nèi)存分配的動作。
相對應(yīng)的兩類析構(gòu)方式:
.由rt_sem_init初始化的semaphore對象 – rt_sem_detach;
.由rt_sem_create創(chuàng)建的semaphore對象 – rt_sem_delete.
1.2 繼承
繼承性是子類自動共享父類之間數(shù)據(jù)和方法的機(jī)制。它由類的派生功能體現(xiàn)。一個類直接繼承其它類的全部描述,同時可修改和擴(kuò)充。繼承具有傳遞性。繼承分為單繼承(一個子類只有一父類)和多重繼承(一個類有多個父類,當(dāng)前RT-Thread的對象系統(tǒng)不能支持)。類的對象是各自封閉的,如果沒繼承性機(jī)制,則類對象中數(shù)據(jù)、方法就會出現(xiàn)大量重復(fù)。繼承不僅支持系統(tǒng)的可重用性,而且還促進(jìn)系統(tǒng)的可擴(kuò)充性。
類似的實現(xiàn)代碼如下程序清單:
/* 父類 */
struct parent_class
{
int a, b;
char *str;
};
/* 繼承于父類的子類 */
struct child_class
{
struct parent class p;
int a, b;
};
/* 操作示例函數(shù)*/
void func()
{
struct child_class obj, *obj_ptr; /* 子類對象及指針 */
struct parent_class *parent_ptr; /* 父類指針 */
obj_ptr = &obj;
/* 取父指針 */
parent_ptr = (struct parent*) &obj;
/* 可通過轉(zhuǎn)換過類型的父類指針訪問相應(yīng)的屬性 */
parent ptr->a = 1;
parent ptr->b = 5;
/* 子類屬性的操作 */
obj ptr->a = 10;
obj ptr->b = 100;
}
在上面代碼中,注意child_class結(jié)構(gòu)中第一個成員p,這種聲明方式代表child_class類型的數(shù)據(jù)中開始的位置包含一個parent_class類型的變量。在函數(shù)func中obj是一個child_class對象,正像這個結(jié)構(gòu)類型指示的,它前面的數(shù)據(jù)應(yīng)該包含一個parent_class類型的數(shù)據(jù)。在第21行的強(qiáng)制類型賦值中parent_ptr指向了obj變量的首地址,也就是obj變量中的p對象。好了,現(xiàn)在parent_ptr指向的是
一個真真實實的parent類型的結(jié)構(gòu),那么可以按照parent的方式訪問其中的成員,當(dāng)然也包括可以使用和parent結(jié)構(gòu)相關(guān)的函數(shù)來處理內(nèi)部數(shù)據(jù),因為一個正常的,正確的代碼,它是不會越界訪問parent結(jié)構(gòu)體以外的數(shù)據(jù)。經(jīng)過這基本的結(jié)構(gòu)體層層相套包含,對象簡單的繼存關(guān)系就體現(xiàn)出來了:父對象放于數(shù)據(jù)塊的最前方,代碼中可以通過強(qiáng)制類型轉(zhuǎn)換獲得父對象指針。
1.3 多態(tài)
對象根據(jù)所接收的消息而做出動作。同一消息為不同的對象接受時可產(chǎn)生完全不同的行動,這種現(xiàn)象稱為多態(tài)性。利用多態(tài)性用戶可發(fā)送一個通用的信息,而將所有的實現(xiàn)細(xì)節(jié)都留給接受消息的對象自行決定,如是,同一消息即可調(diào)用不同的方法。例如:抽象設(shè)備具備接口統(tǒng)一的讀寫接口。串口是設(shè)備的一種,也應(yīng)支持設(shè)備的讀寫。但串口的讀寫操作是串口所特有的,不應(yīng)和其他設(shè)備
操作完全相同,例如操作串口的操作不應(yīng)應(yīng)用于SD卡設(shè)備中。多態(tài)性的實現(xiàn)受到繼承性的支持,利用類繼承的層次關(guān)系,把具有通用功能的協(xié)議存放在類層次中盡可能高的地方,而將實現(xiàn)這一功能的不同方法置于較低層次,這樣,在這些低層次上生成的對象就能給通用消息以不同的響應(yīng)。
對象模型采用結(jié)構(gòu)封裝中使用指針的形式達(dá)到面向?qū)ο笾卸鄳B(tài)的效果,例如:
/* 抽象父類 */
struct parent_class
{
int a;
/* 反映不同類別屬性的方法 */
void (*vfunc)(int a);
}
/* 抽象類的方法調(diào)用 */
void parent_class_vfunc(struct parent_class *self, int a)
{
assert(self != NULL);
assert(slef->vfunc != NULL);
/* 調(diào)用對象本身的虛擬函數(shù) */
self->vfunc(a);
}
/* 繼承自parent class的子類 */
struct child_class
{
struct parent_class parent;
int b;
};
/* 子類的構(gòu)造函數(shù) */
void child_class_init(struct child_class* self)
{
struct parent_class* parent;
/* 強(qiáng)制類型轉(zhuǎn)換獲得父類指針 */
parent = (struct base_class*) self;
assert(parent != NULL);
/* 設(shè)置子類的虛擬函數(shù) */
parent->vfunc = child_class_vfunc;
}
/* 子類的虛擬函數(shù)實現(xiàn) */
static void child class vfunc(struct child class*self, int a)
{
self->b = a + 10;
}
#include <stdio.h>
#include <stdlib.h>
//接口
#ifndef Interface
#define Interface struct
#endif
//類
#ifndef Class
#define Class struct
#endif
//抽象形狀類
Class Shape;
typedef Class Shape shape;
//抽象形狀類的方法聲明
shape* Shape(int edges);
int shape_getEdges(shape *);
int shape_getArea(void);
void _Shape(shape *);
//三角形類
Class Triangle;
typedef Class Triangle triangle;
//三角形類的方法聲明
triangle * Triangle(int bottom, int height);
int triangle_getEdges(triangle *);
int triangle_getArea(triangle *);
void _Triangle(triangle *);
//矩形類
Class Rectangle;
typedef Class Rectangle rectangle;
//矩形類的方法聲明
rectangle * Rectangle(int bottom, int height);
int rectangle_getEdges(rectangle *);
int rectangle_getArea(rectangle *);
void _Rectangle(rectangle *);
//抽象形狀類實現(xiàn)
Class Shape
{
int edges;
int (*getEdges)(shape*);
int (*getArea)(void);
};
//形狀類構(gòu)造函數(shù)
shape* Shape(int edges)
{
shape * obj = (shape *) malloc(sizeof(shape));
obj->edges = edges;
obj->getEdges = shape_getEdges;
obj->getArea = shape_getArea;
return obj;
}
int shape_getEdges(shape* obj)
{
return obj->edges;
}
int shape_getArea(void)
{
return -1;
}
//形狀類析構(gòu)函數(shù)
void _Shape(shape * obj)
{
if(obj == NULL)
return;
free(obj);
}
//三角形類實現(xiàn)
Class Triangle
{
shape * super;
int bottom;
int height;
int (*getEdges)(triangle *);
int (*getArea)(triangle *);
};
//三角形類構(gòu)造函數(shù)
triangle * Triangle(int bottom, int height)
{
triangle* obj = (triangle*) malloc(sizeof(triangle));
//調(diào)用Shape構(gòu)造函數(shù)用于實現(xiàn)繼承
obj->super = Shape(3);
obj->bottom = bottom;
obj->height = height;
obj->getEdges = triangle_getEdges;
obj->getArea = triangle_getArea;
return obj;
}
int triangle_getEdges(triangle * obj)
{
return obj->super->edges;
}
int triangle_getArea(triangle * obj)
{
return (obj->bottom * obj->height) / 2;
}
//三角形類析構(gòu)函數(shù)
void _Triangle(triangle * triangle)
{
_Shape(triangle->super);
if(triangle == NULL)
{
return;
}
free(triangle);
}
//矩形類實現(xiàn)
Class Rectangle
{
shape * super;
int bottom;
int height;
int (*getEdges)(rectangle *);
int (*getArea)(rectangle *);
};
//矩形類構(gòu)造函數(shù)
rectangle * Rectangle(int bottom, int height)
{
rectangle * obj = (rectangle *)malloc(sizeof(rectangle));
//調(diào)用Shape構(gòu)造函數(shù)用于實現(xiàn)繼承
obj->super = Shape(4);
obj->bottom = bottom;
obj->height = height;
obj->getEdges = rectangle_getEdges;
obj->getArea = rectangle_getArea;
return obj;
}
int rectangle_getEdges(rectangle * obj)
{
return obj->super->edges;
}
int rectangle_getArea(rectangle * obj)
{
return (obj->bottom * obj->height);
}
//矩形類析構(gòu)函數(shù)
void _Rectangle(rectangle * obj)
{
_Shape(obj->super);
if(obj == NULL)
{
return;
}
free(obj);
}
//測試
void main(){
shape* shapeObj = Shape(0);
printf("%d\n", shapeObj->getEdges(shapeObj));
printf("%d\n", shapeObj->getArea());
_Shape(shapeObj);
triangle* triangleObj = Triangle(4, 5);
printf("%d\n", triangleObj->getEdges(triangleObj));
printf("%d\n", triangleObj->getArea(triangleObj));
_Triangle(triangleObj);
rectangle* rectangleObj = Rectangle(4, 5);
printf("%d\n", rectangleObj->getEdges(rectangleObj));
printf("%d\n", rectangleObj->getArea(rectangleObj));
_Rectangle(rectangleObj);
}
- c語言鏈表操作示例分享
- 實現(xiàn)去除c語言注釋的小工具
- c語言快速排序算法示例代碼分享
- c語言實現(xiàn)單鏈表算法示例分享
- c語言打開文件函數(shù)使用方法
- c語言獲取文件大小的示例
- c語言strftime時間格式化示例
- c語言文件讀寫示例(c語言文件操作)
- c語言網(wǎng)絡(luò)編程-標(biāo)準(zhǔn)步驟(比較簡單)
- c語言網(wǎng)絡(luò)編程-標(biāo)準(zhǔn)步驟(改進(jìn)版)
- c語言實現(xiàn)的hashtable分享
- c語言尾隊列tailq使用示例分享
- c語言實現(xiàn)系統(tǒng)時間校正工具代碼分享
- linux安裝mysql和使用c語言操作數(shù)據(jù)庫的方法 c語言連接mysql
- linux使用gcc編譯c語言共享庫步驟
- C語言堆棧入門指南
- C語言判斷回文數(shù)的小例子
- c語言多進(jìn)程tcp服務(wù)器示例
相關(guān)文章
Qt設(shè)置窗體(QWidget)透明度的方法總結(jié)
在Qt開發(fā)中,有的時候需要為窗體設(shè)置透明度。這篇文章主要為大家介紹幾個Qt中窗體設(shè)置透明度的方法,文中的示例代碼講解詳細(xì),需要的可以參考一下2022-11-11C語言實現(xiàn)時區(qū)轉(zhuǎn)換函數(shù)的實例
這篇文章主要介紹了C語言實現(xiàn)時區(qū)轉(zhuǎn)換函數(shù)的實例的相關(guān)資料,這里分析需求并提供實現(xiàn)代碼,需要的朋友可以參考下2017-08-08C語言數(shù)據(jù)結(jié)構(gòu)實現(xiàn)銀行模擬
這篇文章主要介紹了C語言數(shù)據(jù)結(jié)構(gòu)實現(xiàn)銀行模擬的相關(guān)資料,通過此文希望大家能理解離散化的方法,希望能幫助到大家,需要的朋友可以參考下2017-08-08VS2010+Opencv+MFC讀取圖像和視頻顯示在Picture控件
這篇文章主要為大家詳細(xì)介紹了VS2010+Opencv+MFC讀取圖像和視頻顯示在Picture控件,具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-08-08Matlab實現(xiàn)黑洞優(yōu)化算法的示例代碼
根據(jù)黑洞現(xiàn)象原理首次提出BH 算法,它在傳統(tǒng)PSO基礎(chǔ)上引入了新的機(jī)制,有效地提高了收斂速度并防止了陷入局部極值的情況發(fā)生.本文將用Matlab實現(xiàn)這一算法,需要的可以參考一下2022-06-06