多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國內(nèi)最全IT社區(qū)平臺 聯(lián)系我們 | 收藏本站
阿里云優(yōu)惠2
您當前位置:首頁 > php開源 > 綜合技術 > 用C實現(xiàn)面向?qū)ο?

用C實現(xiàn)面向?qū)ο?/h1>
來源:程序員人生   發(fā)布時間:2015-04-02 08:21:37 閱讀次數(shù):3913次

    很多開發(fā)工程師都是從學習C語言的"Hello world!"開始的,都知道C語言中的指針是1把利劍,1不留意就傷了自個。但其C語言絕對是1個宗師級語言,這是不可否認的。
    由于我們開發(fā)的需要在多個平臺上運行且需要面向?qū)ο蟮?些特性、所以特寫此文章。權當拋磚引玉。
    
1、概述
     C語言是1種面向進程的程序設計語言、而C++在語言級別上添加了很多新機制(繼承,多態(tài)等)
     因此這里說說使用C語言實現(xiàn)封裝,繼承和多態(tài)的方法。


2、基本知識


1、結構體


在C語言中,常把1個對象用結構體進行封裝,這樣便于對對象進行操作,比如:1
  strcut Point{
int x;
int y;
};




結構體可以嵌套。因此可以把1個結構體當做另外一個結構體的成員:
  struct Circle { 
struct Point point_;
int radius;
};




該結構體與以下定義完全1樣(包括內(nèi)存布置都1樣):
struct Circle { 
int x; 
int y; 
int radius; 
};




2、函數(shù)指針


函數(shù)指針是指針的1種,它指向函數(shù)的首地址(函數(shù)的函數(shù)名即為函數(shù)的首地址),可以通過函數(shù)指針來調(diào)用函數(shù)。


如函數(shù):


int func(int a[], int n);


可以這樣聲明函數(shù)指針:


int (*pFunc)(int a[], int n);


這樣使用:


pFunc = func;


(*pFunc)(a, n);【或PFunc(a, n)】


可以用typedef定義1個函數(shù)指針類型,如:


typdef int (*FUNC)(int a[], int n)


可以這樣使用:


int cal_a(FUNC fptr, int a[], int n)
{
//實現(xiàn)體...
}


3、extern與static


extern和static是C語言中的兩個修飾符,extern可用于修飾函數(shù)或變量,表示該變量或函數(shù)在其他文件中進行了定義;
static也可用于修飾函數(shù)或變量,表示該函數(shù)或變量只能在該文件中使用。可利用它們對數(shù)據(jù)或函數(shù)進行隱藏或限制訪問權限。


3、封裝


在C語言中,可以用結構+函數(shù)指針來摹擬類的實現(xiàn),而用這類結構定義的變量就是對象。


封裝的主要含義是隱藏內(nèi)部的行動和信息,使用者只用看到對外提供的接口和公然的信息。


有兩種方法實現(xiàn)封裝:


1、利用C語言語法。在頭文件中聲明,在C文件中真正定義它。


這樣可以隱藏內(nèi)部信息,由于外部不知道對象所占內(nèi)存的大小,所以不能靜態(tài)的創(chuàng)建該類的對象,只能調(diào)用類提供的創(chuàng)建函數(shù)才能創(chuàng)建。這類方法的缺點是不支持繼承,由于子類中得不到任何關于父類的信息。如:


/**
 * Point的頭文件Point.h(對外提供接口)
 */
#ifndef POINT_H
#define POINT_H


extern const void * Point; /* new(Point, x, y); */


void move(void * point, int dx, int dy);


struct Point {
const void * base;  //繼承Base類,基類指針,放在第1個位置,const是避免修改
int x, y; //坐標
};


#define point_x(p)(((const struct Point *)(p)) -> x)
#define point_y(p)(((const struct Point *)(p)) -> y)


#endif


 
//Point的源文件Point.c
#include <stdio.h>
#include "Point.h"
#include "cnew.h"
#include "Base.h"


/**********Point類自己的構造函數(shù)***********/
static void * Point_New(void * _self, va_list * app) {
struct Point * self = _self;
self->x = va_arg(*app, int);
self->y = va_arg(*app, int);
printf("Point_New self = %p ", self);
return self;
}


/**********Point類自己的析構函數(shù)***********/
static void* Point_Delete(void * _self) {
printf("call Point_Delete self =%p ", _self);
printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ");
return NULL;
}


/**********Point類自己的繪圖函數(shù)***********/
static void Point_Draw(const void * _self) {
const struct Point * self = _self;
printf("Point_Draw at %d,%d ", self->x, self->y);
}


void move(void * _self, int dx, int dy) {
struct Point * self = _self;
printf("call move self =%p ", _self);
self->x += dx;
self->y += dy;
}


static const struct Base _Point = { sizeof(struct Point), Point_New, Point_Delete, Point_Draw };
const void * Point = &_Point;


4、繼承


在C語言中,可以利用“結構在內(nèi)存中的布局與結構的聲明具有1致的順序”這1事實實現(xiàn)繼承。


比如我們要設計1個作圖工具,其中可能觸及到的對象有Point(點),Circle(圓),由于圓是由點組成的,所有可以看成Circle繼承自Point。另外,Point和Circle都需要空間申請,空間釋放等操作,所有他們有共同的基類Base。


#ifndef C_NEW_H
#define C_NEW_H


/**
 * 內(nèi)存管理類頭文件cnew.h(對外提供接口)
 */


void * cnew(const void * base, ...);


void cdelete(void * item);


void draw(const void * self);


#endif /* C_NEW_H */


 
/**
 * 內(nèi)存管理類的源文件:cnew.c
 */
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <stdarg.h>
#include "cnew.h"
#include "Base.h"


void * cnew(const void * _class, ...) {
const struct Base * base = _class;
void * p = calloc(1, base->size);
assert(p);
*(const struct Base **) p = base;
if (base->constructor) {
va_list ap;
va_start(ap, _class);
p = base->constructor(p, &ap);
va_end(ap);
}
return p;
}


void cdelete(void * self) {
const struct Base ** cp = self;
if (self && *cp && (*cp)->destroy)
self = (*cp)->destroy(self);
free(self);
}


void draw(const void * self) {
const struct Base * const * cp = self;
assert(self && *cp && (*cp)->draw);
(*cp)->draw(self);
}
 
/**
 *  基類Base的內(nèi)部頭文件Base.r,對外隱藏
 */
#ifndef BASE_R
#define BASE_R


#include <stdarg.h>


struct Base {
size_t size;
void * (*constructor)(void * self, va_list * app); //構造函數(shù)
void * (*destroy)(void * self);  //析構函數(shù)
void (*draw)(const void * self);//作圖函數(shù)
};


#endif


/**
 * Point的頭文件Point.h(對外提供接口)
 */
#ifndef POINT_H
#define POINT_H


extern const void * Point; /* new(Point, x, y); */


void move(void * point, int dx, int dy);


struct Point {
const void * base;  //繼承Base類,基類指針,放在第1個位置,const是避免修改
int x, y; //坐標
};


#define point_x(p)(((const struct Point *)(p)) -> x)
#define point_y(p)(((const struct Point *)(p)) -> y)


#endif


//Point的源文件Point.c
#include <stdio.h>
#include "Point.h"
#include "cnew.h"
#include "Base.h"


/**********Point類自己的構造函數(shù)***********/
static void * Point_New(void * _self, va_list * app) {
struct Point * self = _self;
self->x = va_arg(*app, int);
self->y = va_arg(*app, int);
printf("Point_New self = %p ", self);
return self;
}


/**********Point類自己的析構函數(shù)***********/
static void* Point_Delete(void * _self) {
printf("call Point_Delete self =%p ", _self);
printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ");
return NULL;
}


/**********Point類自己的繪圖函數(shù)***********/
static void Point_Draw(const void * _self) {
const struct Point * self = _self;
printf("Point_Draw at %d,%d ", self->x, self->y);
}


void move(void * _self, int dx, int dy) {
struct Point * self = _self;
printf("call move self =%p ", _self);
self->x += dx;
self->y += dy;
}


static const struct Base _Point = { sizeof(struct Point), Point_New, Point_Delete, Point_Draw };
const void * Point = &_Point;


/**
 * Circle的頭文件Circle.h(對外提供接口)
 */


#ifndef CIRCLE_H
#define CIRCLE_H


#include "Point.h"


extern const void * Circle; /* new(Circle, x, y, rad) */


struct Circle {
const struct Point pbase;  //繼承Point類,需放在第1位
int radius;
int (*area)(void *self);// 面積,擴大方法
};


#define circle_area(p) (((const struct Circle *)(p)) -> area(p))


#endif




/**
 * Circle的源文件Circle.c
 */
#include <stdio.h>
#include "Circle.h"
#include "cnew.h"
#include "Base.h"


/**********Circle類自己的擴大函數(shù)***********/
static int Circle_Area(void * _self) {
const struct Circle * self = _self;
printf("call Circle_Area self =%p ", _self);
return self->radius * self->radius;
}


/**********Circle類自己的構造函數(shù)***********/
static void * Circle_New(void * _self, va_list * app) {
struct Circle * self = ((const struct Base *) Point)->constructor(_self, app);
self->radius = va_arg(*app, int);
self->area = Circle_Area;
printf("call Circle_New self =%p ", _self);
return self;
}


/**********Circle類自己的構造函數(shù)***********/
static void* Circle_Delete(void * _self) {
printf("call Circle_Delete self =%p ", _self);
printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ");
return NULL;
}


/**********Circle類自己的繪圖函數(shù)***********/
static void Circle_Draw(const void * _self) {
const struct Circle * self = _self;
int x = point_x(self);
int y = point_y(self);
printf("Circle_Draw at %d,%d rad %d ", x, y, self->radius);
}


static const struct Base _Circle = { sizeof(struct Circle), Circle_New, Circle_Delete, Circle_Draw };
const void * Circle = &_Circle;






/**
 * 測試函數(shù)
 */


#include "Circle.h"
#include "cnew.h"


int oo_main(int argc, char ** argv) {
void * p;
int i;
for (i = 0; i < 2; i++) {
if (i == 0) {
p = cnew(Circle, 1, 2, 3);
circle_area(p);
} else {
p = cnew(Point, 1, 2);
}
draw(p);
move(p, 10, 20);
draw(p);
cdelete(p);
}
return 0;
}


/***********************************
 * 測試結果:
 *
 * Point_New self = 0x50a1d8
 * call Circle_New self =0x50a1d8
 * Circle_Draw at 1,2 rad 3
 * call move self =0x50a1d8
 * Circle_Draw at 11,22 rad 3
 * call Circle_Delete self =0x50a1d8
 *
 * Point_New self = 0x5096a0
 * Point_Draw at 1,2
 * call move self =0x5096a0
 * Point_Draw at 11,22
 * call Point_Delete self =0x5096a0
 *
 ************************************/


5、多態(tài)


可以是用C語言中的萬能指針void* 實現(xiàn)多態(tài),接上面的例子:


 //測試main.c
 
int oo_main(int argc, char ** argv) {
void * p;
int i;
for (i = 0; i < 2; i++) {
if (i == 0) {
p = cnew(Circle, 1, 2, 3);
circle_area(p);
} else {
p = cnew(Point, 1, 2);
}
draw(p);
move(p, 10, 20);
draw(p);
cdelete(p);
}
return 0;
}


6、總結


C語言能夠摹擬實現(xiàn)面向?qū)ο笳Z言具有的特性,包括:多態(tài),繼承,封裝等,現(xiàn)在很多開源軟件都了用C語言實現(xiàn)了這幾個特性,包括大型開源數(shù)據(jù)庫系統(tǒng)postgreSQL,可移植的C語言面向?qū)ο罂蚣蹽Object,無線2進制運行環(huán)境BREW。采取C語言實現(xiàn)多態(tài),繼承,封裝,能夠讓軟件有更好的可讀性,可擴大性。


全部的測試代碼:


http://download.csdn.net/detail/andyhuabing/8475335


生活不易,碼農(nóng)辛苦
如果您覺得本網(wǎng)站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生

------分隔線----------------------------
分享到:
------分隔線----------------------------
關閉
程序員人生
主站蜘蛛池模板: 亚洲产国偷v产偷v自拍自拍 | 亚洲乱码在线 | 加勒比一道本综合 | 夜趣第一宅男福社区国产 | 精品中文字幕一区二区三区四区 | 欧美小网站 | 亚洲视频在线网站 | 欧美亚洲国产精品久久久 | 国产成人精品福利站 | 日韩 国产 欧美视频一区二区三区 | 免费在线播放视频 | 一级毛片一 | 天堂日本岛a | 精品在线视频播放 | freexxx性欧美hd丝袜 | 欧美人在线| 欧美日韩欧美日韩 | 欧美xxxx精品另类 | 国产成人系列 | 毛片新网址 | 国内精品久久久久激情影院 | 99精品国产美女福到在线不卡 | 黄色毛片免费网站 | 午夜在线视频国产极品片 | 理论亚洲区美一区二区三区 | 欧美一级做性受 | 中文字幕在线第一页 | a亚洲视频 | 午夜啪啪片 | 国产永久一区二区三区 | 亚洲片在线 | 精品国产麻豆免费网站 | 77777亚洲午夜久久多人 | 免费自拍偷拍视频 | 欧美视频 亚洲视频 | 日韩国产免费一区二区三区 | 国产精品久久久久久久 | 青青青青手机在线视频观看国产 | 亚州都市春色校园小说另类 | 日本免费爱爱视频 | 久久精品国产999久久久 |