日本搞逼视频_黄色一级片免费在线观看_色99久久_性明星video另类hd_欧美77_综合在线视频

國內最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2
您當前位置:首頁 > php開源 > 綜合技術 > 用C實現面向對象

用C實現面向對象

來源:程序員人生   發布時間:2015-04-02 08:21:37 閱讀次數:3914次

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


2、基本知識


1、結構體


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




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




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




2、函數指針


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


如函數:


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


可以這樣聲明函數指針:


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


這樣使用:


pFunc = func;


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


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


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的頭文件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類自己的構造函數***********/
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類自己的析構函數***********/
static void* Point_Delete(void * _self) {
printf("call Point_Delete self =%p ", _self);
printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ");
return NULL;
}


/**********Point類自己的繪圖函數***********/
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語言中,可以利用“結構在內存中的布局與結構的聲明具有1致的順序”這1事實實現繼承。


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


#ifndef C_NEW_H
#define C_NEW_H


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


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


void cdelete(void * item);


void draw(const void * self);


#endif /* C_NEW_H */


 
/**
 * 內存管理類的源文件: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的內部頭文件Base.r,對外隱藏
 */
#ifndef BASE_R
#define BASE_R


#include <stdarg.h>


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


#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類自己的構造函數***********/
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類自己的析構函數***********/
static void* Point_Delete(void * _self) {
printf("call Point_Delete self =%p ", _self);
printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ");
return NULL;
}


/**********Point類自己的繪圖函數***********/
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類自己的擴大函數***********/
static int Circle_Area(void * _self) {
const struct Circle * self = _self;
printf("call Circle_Area self =%p ", _self);
return self->radius * self->radius;
}


/**********Circle類自己的構造函數***********/
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類自己的構造函數***********/
static void* Circle_Delete(void * _self) {
printf("call Circle_Delete self =%p ", _self);
printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ");
return NULL;
}


/**********Circle類自己的繪圖函數***********/
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;






/**
 * 測試函數
 */


#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、多態


可以是用C語言中的萬能指針void* 實現多態,接上面的例子:


 //測試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語言能夠摹擬實現面向對象語言具有的特性,包括:多態,繼承,封裝等,現在很多開源軟件都了用C語言實現了這幾個特性,包括大型開源數據庫系統postgreSQL,可移植的C語言面向對象框架GObject,無線2進制運行環境BREW。采取C語言實現多態,繼承,封裝,能夠讓軟件有更好的可讀性,可擴大性。


全部的測試代碼:


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


生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關閉
程序員人生
主站蜘蛛池模板: 精品国产一 | 久久高清 | 国产午夜精品在线观看 | 免费黄色一级大片 | 欧美精品系列 | 美女一区 | 久久久综合色 | 日韩精品在线观看一区 | 久久久久国产一区 | 免费视频一二三区 | 国产成人精品免费视频大全最热 | 精品国产91久久久久久老师 | 九九热精品在线 | av在线网站观看 | 99国产欧美 | 91精品国产91久久综合 | 成年人视频在线免费观看 | 日韩经典一区二区 | 国产成人综合网 | 91私密视频 | 国产精品亚洲片在线播放 | 簧片在线免费观看 | 自拍偷拍欧美日韩 | 久草热在线 | 国产毛片在线 | 青青草国产精品 | 亚洲一二三区视频 | 黄视频欧美 | 亚洲视频在线一区二区 | 亚洲黄色三级 | 久久91精品国产91久久跳 | 九九热久久这里只有精品 | 精品国产自在精品国产浪潮 | 天堂网2017 | 国产在线一区二区 | 精品一区二区不卡 | 欧美精品一区二区三区一线天视频 | 久久宅男 | 亚洲欧美激情精品一区二区 | 不卡一二三区 | 黄色网址视频免费 |