999精品在线视频,手机成人午夜在线视频,久久不卡国产精品无码,中日无码在线观看,成人av手机在线观看,日韩精品亚洲一区中文字幕,亚洲av无码人妻,四虎国产在线观看 ?

自動支持面向對象特性C程序的開發方案

2008-12-31 00:00:00饒俊朱宏明
電腦知識與技術 2008年35期

摘要:已有前人提出用C語言實現面向對象的方案,但它們都需要開發者人為提供支持面向對象的C語言框架,增加了開發者的負擔。該方案用類C++語法編寫初始代碼,享受面向對象特性,而內部把初始代碼自動轉換成為支持面向對象特性的C代碼,實現了面向對象理念和C語言的無縫對接。文章解析了用C語言實現面向對象的機制及代碼轉換機制,對比該方案和C++編程的效果,證實該方案的優越性。

關鍵詞:面向對象;代碼轉換;C/C++

中圖分類號:TP311文獻標識碼:A文章編號:1009-3044(2008)35-2181-03

An Automated Solution to Develop Object-Oriented C Program

RAO Jun-wen, ZHU Hong-ming

(Software School, Tongji University, Shanghai 201804, China)

Abstract: There are already solutions to make C language support Object-Oriented feature, but in those solutions the code framework supporting that feature needs to be provided by developers. In this solution codes will be written in C++-like grammar, while inside codes will be converted into Object-Oriented C language code, so no gap between Object-Oriented feature and C language exists. This paper analyzed the mechanisms of supporting Object-Oriented feature by using C language and codes converting, and then compared performance of this solution to that of using C++, so its advantage would be proved.

Key words: Object Oriented; codes converting; C/C++

1 方案概述

1.1 當前情況

嵌入式系統是當前最熱門最有發展前景的IT應用領域之一,然而不得不承認的是,由于嵌入式領域硬件資源的限制,絕大多數的嵌入式軟件還是用C語言或匯編來實現的,這一現狀極大影響了開發人員的工作效率和質量。眾所周之,C語言是一種不直接支持面向對象特性的語言,相對于C++等語言來說,其代碼編寫效率低,組織層次紛亂,封裝性差,不利于代碼重用。這樣的代碼,可讀性差,維護難度也很大。如果為避免這種情況而采用C++等支持面向對象特性的編程語言又會顧此失彼。C++雖然支持面向對象特性,但它所具有的其他特性,如虛函數、多重繼承、模板、異常、RTTI等,增加了代碼的復雜性,使其占用更多硬件資源,降低代碼運行的效率,這些都會極大的影響嵌入式系統的性能和成本。因此,在實際應用中使用C++開發嵌入式軟件的情況也較少。

下面本文將介紹一種不依賴編譯器的編程方案,它既具有C語言的執行效率,又支持面向對象特性。

1.2 特點

享受基本的面向對象特性,同時享受C語言的效率。

1) 本方案支持“類”的概念,包括私有成員變量和成員函數,并支持成員函數繼承和多態。

2) 類的定義是通過特殊的hpp頭文件來實現的,這個頭文件的編寫格式和C++基本相同。

3) 方案的重要部分是一個自動代碼轉換工具,它負責將hpp頭文件轉換成純C代碼。最終參加編譯的代碼都是純C代碼,因此,這個方案具有C語言所具有的代碼容量小和執行效率高等特點。

4) 方案內部使用C代碼框架實現類封裝,繼承和多態。

1.3 開發主要流程

(注:本文使用“demoClass”代表用戶定義的某一個“類”。“parentClass”代表這個類的父類。)

1) 編寫頭文件demoClass.hpp和源文件demoClass.c;

2) 轉換hpp頭文件代碼,生成中間C框架文件;

3) 編譯C文件,生成二進制文件。

2 方案設計

2.1框架

demoClass.hpp:頭文件,用于存放類的定義信息。

demoClass.c:源文件,用于存放類成員函數的實現。

demoClass.h:公共頭文件,向外提供函數接口和數據定義。

demoClass_priv.h:私有頭文件,僅供類內部的源文件使用,存放私有數據成員的定義及私有成員函數的聲明。

demoClass_info.c:源文件,用于存放類的信息結構體,以及類的構造函數定義。

testMain.c:測試文件,使用類的對象實例完成特定功能。

2.2源代碼編寫結構設計

2.2.1頭文件 .hpp VS C++頭文件.h

1) 所有public函數須都是虛函數,除了構造和析構函數。

2) 只支持private數據成員。

3) 與本類虛函數對應的實體函數在private下聲明。

4) 用以重載父類函數的實體函數在private下聲明。

2.2.2源文件 .c VS .cpp

1) 添加#include \"demoClass_priv.h\"私有成員內容。

2) 對象初始化函數和析構函數:

demoClassInit():對象初始化函數,各函數指針初始化。

demoClassDelete():析構函數,完成“析構”動作。

3) this: 成員函數指針;thisd: 數據成員指針

2.2.3 代碼范例

2.3 中間c代碼設計及其機制

代碼轉換工具將通過給予的hpp文件,自動生成C語言代碼框架,由他們實現各項面向對象的特性。

2.3.1 類結構

經過轉換后的C代碼分別使用兩個結構體存儲類的數據如圖2、圖3。

1) 使用demoClass 結構體存儲函數指針集以及私有數據成員結構體對象的地址。

Typedef struct {

void * pData;

errCode ( *Delete )(CMPHANDLE);

errCode ( *virtualFunc_parent1 )(CMPHANDLE);

errCode ( *virtualFunc_demo1 )(CMPHANDLE);} demoClass;

在成員函數內部,“this”指針指向demoClass對象。而thisd 的內容就是 this->pData。

2) 使用demoClass_data結構體存儲私有數據成員,由于其定義只在demoClass.c中,它并不暴露給外部類。

Typedef struct {

int privParentData1;

int privDemoData1;} demoClass_data;

雖然在對象demoClass中保存了對象demoClass_data的地址,但由于后者的定義并未公開,外部并不知道這個地址空間存儲了哪些數據,而成員函數是在demoClass.c中定義的,他們是“看”的見這張定義表的,所以只有本類的成員函數知道如何“按圖索驥”,這從一定程度上實現了隱藏類的私有成員。

3) 使用結構體ClassInfo的對象來存儲每一個類的信息,包括類名,父類ClassInfo對象指針,demoClass和demoClass_data結構體大小。每個類對應的ClassInfo對象是這個類唯一的全局變量,任何時候用戶可以調用類對應的“構造函數”制造出一個對象實例。

4) “this”和thisd指針

為了能使類的成員函數訪問本類的其他成員函數以及本類的私有數據,成員函數必須知道本對象的地址和數據成員地址,在C++中,這些是由C++編譯器內部提供this指針來實現的;在本方案中,每個成員函數都以第一個參數作為一個固定的輸入參數,來獲得本對象的地址,進而獲得數據成員的地址。this是demoClass型指針,thisd是demoClass_data型指針,它們指向各自的結構體對象。

5) 類的創建和消亡

① “構造函數”demoClassNew()

demoClassNew()是這個對象唯一暴露在外的全局函數。用戶可以通過調用它來創建對象。

demoClass* demoClassNew()

{demoClass* h= (demoClass*)ObjCreateAlloc(demoClassInfo);

demoClassInit(h);

return h;}

a. 所有的類都通過調用ObjCreateAlloc (ClassInfo *)來實際創建對象,它依據給定的ClassInfo數據,獲得demoClass和demoClass?_data的結構體大小,分別給它們分配內存空間,并返回demoClass地址,而demoClass_data的地址則保存在demoClass之中。

ObjCreateAlloc()函數將在后文中介紹。

b. 類被創建之后,由demoClassInit()來進行初始化,基本的動作包括函數指針和成員變量的初始化,還可以有用戶自定義的動作。

② “析構函數”負責清理用完的數據或內存,并最終釋放對象自己的內存空間。

2.3.2 繼承

1) 派生類的數據繼承:成員函數指針和成員變量

派生類通過照搬基類數據的方式來實現函數和數據繼承。這種照搬的工作是由代碼轉換工具依據繼承關系完成的。在生成的C代碼中,用于存儲派生類數據的結構體demoClass,其前端數據和基類結構體parentClass的數據完全一 致 ,新 增 加 的 函數指針緊接其后。demoClass_data新增加的成員變量也同理。這樣,派生類就完全包含了一份與基類一致的公有函數指針和數據拷貝。當然,這些函數指針可能指向與基類不同的函數實體,其數據成員也可能存儲不同的內容,這取決于構造函數的實現。

2) 構造和析構函數的繼承

派生類的構造函數在自己的初始化函數開頭,先調用基類的初始化函數,它負責初始化繼承自基類的成員,在這個階段,派生類被裝扮成基類的樣子。然后派生類執行自己的初始化動作,在這個階段,派生類給新增加的函數成員和數據成員賦值,也可以修改來自基類的成員。

派生類的析構函數也分成兩部分,先清理自己新增加的成員,然后在末尾調用基類的析構函數,來清理來自基類的成員,最終釋放自己占用的內存。

3) 成員函數的繼承

與上節類似,被重載的成員函數,其新的函數實體可以包含對基類成員函數的調用,也可以不調用,完全重寫。

2.3.3 封裝

1) 通過以上的結構設計,C語言中間代碼實現了封裝性:

任何一個對象創建之后,只能通過這個對象的句柄訪問其公開的函數接口,外界看不見內部的數據,也無法通過合法的手段直接操作它們。而在對象創建之前,與這個類相關的全局元素只有兩個:全局變量demoClassInfo和全局函數demoClassNew( )。

2) 公共根類

在這套方案中,任何一個類的對象,其創建和消亡都會涉及到這個類基礎數據的處理,包括內存的分配和內部數據結構的初始化,這些是中間代碼的內容,用戶應無需關心它們,因此我們建立一個公共的虛基類rootObj,用它來封裝這些內部的操作。用戶如果要建立新的基類customClass,只需繼承這個虛基類,填寫好它對應的初始化函數customInit( )和析構函數customDelete()。根據代碼的繼承機制,新的類會遞歸調用對應的構造、析構函數,最終調用到虛基類rootObj的構造、析構函數,從而最終完成類的創建和消亡。

① 前面已經提到,類的構造函數demoClassNew()分成ObjCreateAlloc()和demoClassInit()兩個部分。

ObjCreateAlloc()函數把所有的類都當作虛基類來創建,包括給兩個結構體分配內存,并初始化pData指針。

CMPHANDLE ObjCreateAlloc(const ClassInfo* ci)

{rootObj* this;

rootObj_data* thisd;

this=malloc(ci->isize); //給demoClass分配內存

//給demoClass_data分配內存并把地址保存在pData中

this->pData = malloc(ci->dsize) ;

return this;}

② 虛基類的析構函數,負責釋放類結構所占用的內存

errCode rootObjDelete(CMPHANDLE h)

{ THIS_PTR_DEF;

free(h);

return SUCCESS;}

2.3.4 多態

本方案把所有成員函數都設置成虛函數,在內部通過函數指針的方式來實現。當派生對象要重載基類對象的某個成員函數的時候,就把對應的函數指針指向新的函數實現實體,這樣,一個同名的成員函數,根據類的不同完成著不同的操作,從而實現了多態。

2.4 代碼轉換工具的工作

總結如下:根據給予的demoClass.hpp文件,

1) 生成demoClass.h文件:

① include 父類的頭文件parentClass.h。

② 生成demoClass結構體,其中,把所有的成員函數,轉換成同名的函數指針,如果有父類,則把父類的成員函數指針放在開頭。

③ 聲明demoClassInfo變量和demoClassNew()函數。

2) 生成demoClass_priv.h文件:

① include 父類的頭文件parentClass.h。

② 生成demoClass_data結構體,其成員就是類的所有私有成員,如果有父類,則把父類的成員變量放在開頭。

③ 聲明父類的初始化和析構函數,及成員實體函數。

④ 聲明本類的初始化函數和成員實體函數。

3) 生成demoClass_info.c文件

① include本類的兩個頭文件 demoClass.h和demoClass_priv.h。

② 定義demoClassInfo變量,并賦值。

③ 定義本類的構造函數demoClassNew()。

這個代碼轉換工具由perl語言編程實現,可以集成在makefile中成為代碼預處理的一部分。

3 此方案和C++方案的對比

在linux環境下,功能完全相同的兩個程序:

4 結束語

通過此方案的轉換手段,可以在基本保持C語言性能的基礎上,開發出支持面向對象的C程序,而且不增加開發人員的額外負擔。它大大提高了程序的可復用性和可維護性,為開發結構更加復雜、代碼更加清晰易讀的嵌入式軟件系統提供了可能。在實際應用中,采用此方案的軟件代碼明顯比用原C語言實現的同樣功能的代碼更加受開發人員的歡迎。

參考文獻:

[1] 章遠陽,楊芙清,邵維中.C++語言的面向對象特性分析[J].計算機工程與應用,1992(9).

[2] 張泰樂,肖孫圣,倪宏.面向對象基本特性的c語言實現[J].微計算機應用,23(6).

[3] Meyers S,Effective C++[M].武漢:華中科技大學出版社,2005.

[4] 劉宇,王煒,張見威.C++語言面向對象機制的底層實現[J].華南師范大學學報,1998(4).

主站蜘蛛池模板: 亚洲91精品视频| 精品自窥自偷在线看| 全部免费毛片免费播放 | 性网站在线观看| 国内精品久久人妻无码大片高| 国产精品一区不卡| 日本免费a视频| 亚瑟天堂久久一区二区影院| 5555国产在线观看| 色有码无码视频| 亚洲欧州色色免费AV| 人人91人人澡人人妻人人爽 | 精品一区二区久久久久网站| 狠狠亚洲婷婷综合色香| 99re在线视频观看| 亚洲精品卡2卡3卡4卡5卡区| 国产精品第一区| 国产精品一区在线麻豆| 在线免费观看a视频| 中文字幕资源站| 久久久久人妻精品一区三寸蜜桃| 99国产精品免费观看视频| 国产成人夜色91| 亚洲中文字幕无码爆乳| 中文字幕天无码久久精品视频免费| 亚洲成人网在线观看| AV不卡在线永久免费观看| 经典三级久久| 99999久久久久久亚洲| 999在线免费视频| 欧美成人午夜在线全部免费| 中文字幕在线视频免费| 国产亚洲精久久久久久无码AV | 国产网友愉拍精品| 日本道综合一本久久久88| 国产人成网线在线播放va| 亚洲日韩在线满18点击进入| 精品视频91| 日韩一级二级三级| 久久先锋资源| 欧美精品在线视频观看| 欧美精品高清| 亚洲国产中文在线二区三区免| vvvv98国产成人综合青青| 色九九视频| 国产精品综合久久久| 亚洲av无码牛牛影视在线二区| 在线观看欧美国产| 久久99蜜桃精品久久久久小说| 91po国产在线精品免费观看| 日韩精品一区二区三区swag| 91黄视频在线观看| 中文字幕欧美日韩| 亚洲啪啪网| 四虎影视无码永久免费观看| 一级不卡毛片| 国产精品yjizz视频网一二区| 91精品视频在线播放| 狠狠色婷婷丁香综合久久韩国| 日韩视频精品在线| 亚洲视频在线青青| 色哟哟国产精品| 狠狠综合久久| 欧美在线一二区| аⅴ资源中文在线天堂| 超碰91免费人妻| 国产v精品成人免费视频71pao| 日韩欧美91| 四虎成人精品| 国产主播喷水| 国产一区二区色淫影院| 91免费国产高清观看| 国产尤物jk自慰制服喷水| 国产激爽大片高清在线观看| 国产精欧美一区二区三区| 99免费视频观看| 天天综合网站| 国产午夜精品鲁丝片| 欧美成人午夜影院| 国产在线精彩视频二区| 91久久偷偷做嫩草影院| 这里只有精品免费视频|