C语言实现封装特性

注:本文原型摘自《架构整洁之道》第5章 面向对象编程,经过作者加工修改

1. 封装特性

封装是面向对象编程的基本思想之一,通过采用封装特性,我们可以把一组相关联的数据和函数圈起来,使圈外面的代码只能看见部分函数,数据则完全不可见。

然而由于C++编译器必须知道每个类实例的大小,因此要求类的成员变量必须在该类的头文件中声明,这样反而违背了封装性。

反而非面向对象的C语言,可以通过一些手法实现完美的封装特性。

2. C实现封装举例

namedpoint.h 代码如下, 头文件对外声明NamedPoint类型的结构体,和4个相关的函数。
注意该头文件中,并未暴露NamedPoint的数据细节,即外部调用方只知道存在NamedPoint这个数据结构,但是无法得知NamedPoint内部数据是如何组织的。
外部模块只能通过头文件提供的4个函数去操作NamedPoint这个数据结构。

// namedpoint.h  
#ifndef __NAMEDPOINT_H__
#define __NAMEDPOINT_H__

typedef struct _NamedPoint NamedPoint;

NamedPoint* makeNamedPoint(int x, int y, char* name);
void setName(NamedPoint* p, char* name);
char* getName(NamedPoint* p);
double distance(NamedPoint* from, NamedPoint* to);

#endif

namedpoint.c 文件中实现了NamedPoint结构体的实现细节,和提供给外部调用的函数。
这里NamedPoint结构体的数据完全封装在namedpoint.c文件中,调用NamedPoint的模块是无法得知其内部数据的组织细节。

// namedpoint.c 
#include <stdlib.h>
#include <math.h>
#include "namedpoint.h"

struct _NamedPoint
{
    double x, y;
    char* name;
};


NamedPoint* makeNamedPoint(int x, int y, char* name)
{
    NamedPoint* p = (NamedPoint*)malloc(sizeof(NamedPoint));
    p->x = x;
    p->y = y;
    p->name = name;
    return p;
}

void setName(NamedPoint* p, char* name)
{
    p->name = name;
}

char* getName(NamedPoint* p)
{
    return p->name;
}

double distance(NamedPoint* from, NamedPoint* to)
{
    double dx = from->x - to->x;
    double dy = from->y - to->y;
    return sqrt(dx * dx + dy * dy);
}

main.c中提供了调用示例,在main.c中,仅根据namedpoint.h头文件中提供的信息来使用NamedPoint类。

// main.c
#include <stdio.h>
#include <stdlib.h>
#include "namedpoint.h"


int main(void)
{
    NamedPoint* orgin = makeNamedPoint(0.0, 0.0, "orgin");
    NamedPoint* upperRight = makeNamedPoint(6.0, 8.0, "upperRight");

    printf("distance=%f\n", distance(orgin, upperRight));
    return 0;
}

调试执行结果如下:
执行结果

上面的例子中,NamedPoint类在namedpoint.c中实现数据组织和函数实现。在namedpoint.h中,仅提供了数据类型名,和外部接口函数,从外部并无法得知NamedPoint类内部数据的组织方式。main.c中使用NamedPoint类时,也仅通过接口使用,并无法知道其内部数据的组织方式。由此达到了比较理想的“封装”特性。

3. 总结

如上,虽然C并不是面向对象的编程语言,但是仍然以实现隐藏数据细节的方式,实现完美的封装效果。

posted on 2024-04-25 15:52  TheShore  阅读(26)  评论(0编辑  收藏  举报