C语言实现封装、继承和多态

转载 2015年07月07日 17:36:35

1、  概述

C语言是一种面向过程的程序设计语言,而C++是在C语言基础上衍生来了的面向对象的语言,实际上,很多C++实现的底层是用C语言实现的,如在Visual C++中的Interface其实就是struct,查找Interface的定义,你可以发现有这样的宏定义:

#ifndef Interface
    #define Interface struct
    #endif

C++在语言级别上添加了很多新机制(继承,多态等),而在C语言中,我们也可以使用这样的机制,前提是我们不得不自己实现。

本文介绍了用C语言实现封装,继承和多态的方法。

2、  基本知识

在正式介绍C语言实现封装,继承和多态事前,先介绍一下C语言中的几个概念和语法。

(1)    结构体

在C语言中,常把一个对象用结构体进行封装,这样便于对对象进行操作,比如:

strcut Point
{
    int x;
    int y;
};

结构体可以嵌套。因而可以把一个结构体当成另一个结构体的成员,如:

struct Circle 
{
    struct Point point_;
    int radius;
};

该结构体与以下定义完全一样(包括内存布置都一样):

struct Circle 
{
    int x;
    int y;
    int radius;
};


(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
{
    int x;
    int y;
};
point * new_point()
{
    point * new_point_ = (point *) malloc(sizeof(point));
    return new_point_;
}
void free_point(point *point_)
{
    if(point_ == NULL)
        return;
    free(point_);
}

(2)    把私有数据信息放在一个不透明的priv变量或者结构体中。只有类的实现代码才知道priv或者结构体的真正定义。如:

#ifndef POINT _H
#define POINT_H

typedef struct Point point;
typedef struct pointPrivate pointPrivate;
strcut Point
{
    Struct pointPrivate *pp;
};
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 x;
    int y;
}
int get_x(point *point_)
{
    return point_->pp->x;
}
int get_y(point *point_)
{
    return point_->pp->y;
}
//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, ...)
{
    const struct Base * base = _base;
    void * p = calloc(1, base->size);
    assert(p);
    *(const struct Base **) p = base;
    if (base ->ctor)
    {
        va_list ap;
        va_start(ap, _base);
        p = base ->ctor(p, &ap);
        va_end(ap);
    }
    return p;
}
void delete (void * self)
{
    const struct Base ** cp = self;
    if (self && * cp && (* cp) —> dtor)
        self = (* cp) —>dtor(self);
    free(self);
}
void draw (const void * self)
{
    const struct Base * const * cp = self;
    assert(self &&* cp && (* cp)->draw);
    (* cp) ->draw(self);
}

//基类:base.h

#ifndef BASE_H
#define BASE_H
struct Base
{
    size_t size; //类所占空间
    void * (* ctor) (void * self, va_list * app); //构造函数
    void * (* dtor) (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); */
#endif

//Point内部头文件(外面看不到):point.r

#ifndef POINT_R
#define POINT_R
struct Point
{
    const void * base; //继承,基类指针,放在第一个位置,const是防止修改
    int x, y;        //坐标
};
#endif

//Point的C文件:point.c

#include “point.h”
#include “new.h”
#include “point.h”
#include “point.r”
static void * Point_ctor (void * _self, va_list * app)
{
    struct Point * self = _self;
    self ->x = va_arg(* app, int);
    self ->y = va_arg(* app, int);
    return self;
}

static void Point_draw (const void * _self)
{
    const struct Point * self = _self;
    printf(“draw (%d,%d)”, self -> x, self -> y);
}
static const struct Base _Point = {
    sizeof(struct Point), Point_ctor, 0, Point_draw
};
const void * Point = & _Point;

//测试程序:main.c

#include “point.h”
#include “new.h”
int main (int argc, char ** argv)
{
    void * p = new(Point, 1, 2);
    draw(p);
    delete(p);
}
同样,Circle要继承Point,则可以这样:
struct Circle
{
    const struct Point point; //放在第一位,可表继承
    int radius;
};


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用法》:

http://www.cnblogs.com/hishope/archive/2008/08/28/1278822.html

(2)        《三、使用GObject——私有成员和静态变量》:

http://blog.csdn.net/wormsun/archive/2009/11/25/4874465.aspx

(3)        《技巧:用 C 语言实现程序的多态性》:

http://www.ibm.com/developerworks/cn/linux/l-cn-cpolym/index.html?ca=drs-

(4)        书籍《Object-Oriented Programming With ANSI-C》

8、  代码下载

本文中的代码可以在此处下载:代码下载

原创文章,转载请注明: 转载自董的博客

本文链接地址: http://dongxicheng.org/cpp/ooc/

作者:Dong,作者介绍:http://dongxicheng.org/about/

本博客的文章集合:


相关文章推荐

C语言实现C++的封装继承与多态

1、 概述 C语言是一种面向过程的程序设计语言,而C++是在C语言基础上衍生来了的面向对象的语言,实际上,很多C++实现的底层是用C语言实现的,如在Visual C++中的Interface其实就...

C语言实现C++的封装继承和多态

 1、  概述 C语言是一种面向过程的程序设计语言,而C++是在C语言基础上衍生来了的面向对象的语言,实际上,很多C++实现的底层是用C语言实现的,如在Visual C++中的Interf...

用C语言实现c++的封装、继承、多态

c++的三大特性:封装、继承、多态 如何用C语言实现呢? 1、封装 在c++中,将数据与数据的操作封装在一起,也就是类 类只对外界开放接口,将接口的实现细节与类的一些属性,变量隐藏起来,达到数...

C语言实现封装、继承和多态

1、  概述 C语言是一种面向过程的程序设计语言,而C++是在C语言基础上衍生来了的面向对象的语言,实际上,很多C++实现的底层是用C语言实现的,如在Visual C++中的Interface其...

软件设计本质论(Essential Design) —白话面向对象 (转注:关于c语言实现封装继承多态的一堆博文)

软件设计本质论(Essential Design) —白话面向对象 分类: 23.设计本质论系列 2006-08-15 21:424361人阅读 评论(11)收藏 举报 软件设计本质论(E...

C语言面向对象的封装、继承和多态的思想

#include #include #define Jicheng #define Fengzhuang #define Duotai /*思想为结构体的嵌套*/ #ifdef Jic...

C语言和设计模式(继承、封装、多态)

【 声明:版权所有,欢迎转载,请勿用于商业用途。  联系信箱:feixiaoxing @163.com】     记得还在我们大学C++第一门课的时候,老师就告诉我们说,C++是一门面向对象...

C语言下的封装、继承与多态

上次课,钱SIR提到,Liux下面也有很多用C实现的面向对象的结构。比较感觉兴趣,就在网上查了一些资料,原来C语言模拟实现面向对象语言所具有的特性:多态,继承,封装,也是一件很简单的事儿。并且现在很多...

从C语言的角度出发理解C++的封装继承和多态

从C语言的角度出发理解C++的封装继承和多态 在学习C++面对对象程序设计的时候,会把C++类的使用和C结构体的使用作比较。我们都知道C++是C语言的继承,而C++最明显的特征就是面对对象,那么C...

C语言和设计模式(继承、封装、多态)

记得还在我们大学C++第一门课的时候,老师就告诉我们说,C++是一门面向对象的语言。C++有三个最重要的特点,即继承、封装、多态。等到后来随着编码的增多和工作经验的积累,我也慢慢明白了面向对象的含义。...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)