scribble

Hao, a coder

Blog Series GitHub About

02 Jul 2016
C语言的面向对象编程-模块化

在从事了一段时间嵌入式开发的过程中,深感在缺乏单元测试框架下开发效率的低下造成的苦闷。这期间也曾经准备进行C语言单元测试的转变,但是由于嵌入式开发本身的局限,以及缺乏进行C单元测试的经验,最终以失败告终。

直到遇到了偶然间看到了花井志生所著、杨文轩翻译的《C现代编程》一书,书中列举的经验方法是我的眼前一亮,特别摘取其中的重点部分分享给大家,希望我们都有所获的。

这篇文章遵循书中的脉络,本篇是这个系列的第一篇:Ubuntu环境下Eclipse测试环境搭建。欢迎大家访问我的博客,代码可以在@Zuozuohao下载。

关于Eclipse的安装和配置,大家可以Google之,在这里我就不重复做轮子了,请大家谅解。

模块化概述

在进行编程的过程中,经常会出现冗长和单调的代码,例如: 1. 靠数字区分的函数名,get2()和get3() 2. 长达上前行的冗余文件,里面充斥着大量重复的代码(多数是粘帖过来的)

大多数人将这些归咎于C语言的过程式编程,但是既然C语言提供了数据类型和函数功能,那么就可以将这些数据和对于的函数整合在一起,进行模块化编程。

这篇文章将初步解析C的面向对象编程机制,这些对于嵌入式编程有很大的帮助。

Flash读写示例

以操作嵌入式常用的flash为例进行说明,下面的是一个模仿flash行为的代码,在以后的每篇Post中都将使用这个例子,直到再也不能使用为止(希望大家谅解我的懒惰):

cmodel/flash.h

#ifndef _FLASH_H
#define _FLASH_h

typedef char error;

error write(char *values , long int address);
error read(char *values , long int address);

#endif


cmodel/flash.c

#include "flash.h"
error write(char *values , long int address) {
    configFlashForWriting();
    printf("successful wirte values\n");
    return 0;
}
error read(char *values , long int address) {
    configFlashForReading();
    printf("successful read values\n");
    return 0;

}

void configFlashForWriting() {
    printf("successful config for writing flash\n");
}

void configFlashForReading() {
    printf("successful config for reading flash\n");
}

main函数的代码为:

main.c

#include <stdio.h>
#include "flash.h"

int main(int argc, char const *argv[])
{
    char *buff;

    char k = write(buff, 0);
    printf("Hello flash\n");

    return 0;
}

输出函数是:

successful config for writing flash
successful wirte values
Hello flash

C代码的模块化

假如我们现在要增加一个文件函数testStatic.c,该文件里面包含与flash.c文件中的同名函数(项目代码最好不要这么写): void configFlashForWriting() void configFlashForReading()

testStatic.c


#include "flash.h"

void configFlashForWriting() {
    printf("successful config for writing flash\n");
}

void configFlashForReading() {
    printf("successful config for reading flash\n");
}

如果直接在工程中直接命名的话,肯定会出错,因为这两个函数直接暴露在全局变量之中,导致命名冲突。这个时候我们就需要static出手了,具体代码如下:

cmodel/testStatic.c

#include "flash.h"

static void configFlashForWriting();
static void configFlashForReading();

void configFlashForWriting() {
    printf("successful config for writing flash\n");
}

void configFlashForReading() {
    printf("successful config for reading flash\n");
}

cmodel/flash.c

#include "flash.h"

static void configFlashForWriting();
static void configFlashForReading();
error write(char *values , long int address) {
    configFlashForWriting();
    printf("successful wirte values\n");
    return 0;
}

...

点击这里下载程序代码

static的作用在于使变量或者函数名只在本文件单位内有效,从而避免代码间命名的冲突,提高C代码的模块化程度,是C模块化常用的方法。

  1. static可以使我们选择性的暴露代码给外部调用,从而使被修饰的变量和函数在作用域局限于单个文件。
  2. 模块化方法同样减少了项目代码间的耦合程度,避免了代码间的冲突,给后续维护和扩展带来了很大的便利。

参考资料 1. 《C现代编程》,花井志生/著 杨文轩/译。


Til next time,
at 00:00

scribble

Blog Series GitHub About