《电子技术应用》
您所在的位置:首页 > 嵌入式技术 > 设计应用 > 用C语言实现类实例化的研究
用C语言实现类实例化的研究
2016年微型机与应用第23期
杨韬
广州致远电子股份有限公司,广东 广州 510660
摘要: 多年以来,C语言在嵌入式软件开发中被广泛使用,但由于开发人员和应用场景等原因,面向对象、设计模式等优秀的软件开发方法始终没有很好地运用起来。时至今日,物联网等应用的兴起,给嵌入式软件开发带来新的挑战,而传统的面向过程开发已经难以支撑这些复杂的应用。因此,有必要在嵌入式软件开发中引入面向对象、设计模式等优秀的软件开发方法。面向对象是现代软件方法的根基,面向对象体现在类上,使用类来创建对象的过程就是实例化。文章结合C语言的特性,对使用C语言实现类实例化进行了讨论。
Abstract:
Key words :

  杨韬

  (广州致远电子股份有限公司,广东 广州 510660)

       摘要:多年以来,C语言在嵌入式软件开发中被广泛使用,但由于开发人员和应用场景等原因,面向对象、设计模式等优秀的软件开发方法始终没有很好地运用起来。时至今日,物联网等应用的兴起,给嵌入式软件开发带来新的挑战,而传统的面向过程开发已经难以支撑这些复杂的应用。因此,有必要在嵌入式软件开发中引入面向对象、设计模式等优秀的软件开发方法。面向对象是现代软件方法的根基,面向对象体现在上,使用类来创建对象的过程就是实例化。文章结合C语言的特性,对使用C语言实现类实例化进行了讨论。

  关键词: C语言;面向对象;类;实例化

  中图分类号:TP312文献标识码:ADOI:10.19358/j.issn.16747720.2016.23.004

  引用格式:杨韬. 用C语言实现类实例化的研究[J].微型机与应用,2016,35(23):15-17.

0引言

  物联网等应用的兴起,给嵌入式软件开发带来新的挑战,而传统的面向过程开发已经难以支撑这些复杂的应用。因此,有必要在嵌入式软件开发中引入面向对象、设计模式等优秀的软件开发方法。本文讨论了如何使用C语言来实现类的实例化。在C++等面向对象语言中对类做了原生的支持,使用new这类关键字即可实例化一个对象。尽管C语言并不支持new,但是通过对实例化过程的分析和拆分,也能实现实例化。

1基本概念[1]

  1.1类

  面向对象有封装、继承、多态三大特性,这些特性主要通过类来体现。类就是一个封装了属性以及相关操作的代码的逻辑实体。

  类具有属性,它是对象的状态的抽象,用数据结构来描述类的属性。

  类具有方法,它是对象的行为的抽象,用方法名和实现该操作的方法来描述。

  除了封装属性和操作外,类还具有访问控制的能力,比如,某些属性和方法可以是私有的,不能被外界访问。通过访问控制,能够对内部数据提供不同级别的保护,以防止外界意外地改变或使用了私有部分。不同的编程语言提供的访问控制等级不尽相同,但都有公有、私有两个等级。

  类是抽象的数据类型,在内存中并不存在(Python等动态语言除外),只有类的实例存在于内存中。

  1.2对象

  对象是人们要进行研究的任何事物,从最简单的整数到复杂的飞机等均可看作为对象,它不仅能表示具体的事物,还能表示抽象的规则、计划或事件。

  对象具有状态,一个对象用数据值来描述它的状态。

  对象还有操作,用于改变对象的状态,对象及其操作就是对象的行为。

  对象实现了数据和操作的结合,使数据和操作封装于对象的统一体中。

  1.3实例化

  用类创建对象的过程就是实例化,创建的对象被称为类的实例。实例化包含两个步骤,第一步是分配对象的内存,第二步是初始化对象的内存。

2类封装的C语言实现

  类的第一大特性为封装,封装即将对象的属性和方法封装在一起,在C语言中可以使用.C、.H和结构体实现类的封装特性。

  以图1中Human类为例,可以使用human.h、human.c、struct human三个元素来完成封装,human.c为human.h中函数声明的实现,本文不讨论这些细节,所以只给出如下human.h的关键代码片段:

图像 001.png

  typedef struct human {

  const char *name;

  int_money;

  } human_t;

  human_t *human_init (human_t *p_this, const char *name, int money);

  voidhuman_talk (human_t *p_this, const char *p_words);

  voidhuman_buy (human_t *p_this, const char *p_something, unsigned price, unsigned count);

  voidhuman_deinit (human_t *p_this);

3类实例化的C语言实现

  实例化包含两个步骤:分配对象的内存和初始化对象的内存。接下来本文以图1中Human类的实例化为例,讨论C语言如何实现类的实例化。

  3.1对象的内存

  如果把类看做类型,那么类的实例就是变量,既然是变量,那么就有动态变量、静态变量和栈变量之分。在C语言中,使用malloc()这类动态内存分配函数得到的变量就是动态变量;全局变量和加了static关键字的变量就是静态变量;在函数内创建的局部变量就是栈变量。下面的代码展示了C语言中的这几类变量:

  #include "human.h"

  struct humang_john;/* 静态变量 */

  static struct human __g_john;/* 静态变量 */

  void foo (void)

  {

  static struct human s_john;/* 静态变量 */

  struct human john;/* 栈变量 */

  struct human*p_john = malloc(sizeof(*p_john));

  /* 动态变量 */

  }

  站在内存的角度,可以把类看做结构体类型,类的实例就是结构体变量,因此,对象也就有动态对象、静态对象和栈对象之分,它们之间的区别如表1所示。

图像 002.png

  free()

  释放内存内存分配可能失败,花费的时间可能不确定;需要处理内存分配失败的情况,增加程序的复杂性可以在需要时创建和销毁对象静态对象位于.data、

  .bss内存段需要编译时确定对象的数量;一直占用内存;对象数量太多太大时会影响程序启动时间确定性好,只要程序能够运行起来,就一定能够创建成功栈对象位于系统

  栈、对象栈对象太大会导致栈溢出自动完成对象内存的分配和回收

  对于嵌入式软件中的C面向对象编程,充分理解表1中的这三类对象是非常有必要的。大多数情况下,一个类都要能够被实例化为静态对象。

  3.2对象的初始化

  初始化对象就是初始化对象的内存,在初始化之前,必然要先得到对象的内存(上一小节已讨论),但无论对象的内存是何种类型,初始化的操作都是相同的。在JAVA等编程语言中,完成此操作的函数被称作构造函数,使用C语言来实现就是一个名为xxxx_init()的初始化函数,也可称之为构造函数。

  以Human类为例,它的初始化函数human_init()如下面的代码所示,可留意到对象的内存需要显式传递给它。

  human_t *human_init (human_t *p_this, const char *name, int money)

  {

  p_this->name = name;

  p_this->_money = money;

  return p_this;

  }

  3.3实例化

  前面两小节分别讨论了对象的内存和对象的初始化,这两步组成了实例化。下面的代码展示了不同类型对象的实例化:

  #include "human.h"

  human_tg_john;/* 静态对象 */

  statichuman_t__g_jen;/* 静态对象 */

  void foo (void)

  {

  static human_ts_jack;/* 静态对象 */

  human_t tom;/* 栈对象 */

  human_t*p_lee_mem= malloc(sizeof(*p_lee_mem));

  /* 动态对象 */

  // 实例化上面定义的静态对象、动态对象和栈对象

  human_t *p_john= human_init(&g_john, "john", 100);

  human_t *p_jen = human_init(&__g_jen, "jen", 100);

  human_t *p_jack = human_init(&s_jack, "jack", 100);

  human_t *p_tom = human_init(&tom, "tom", 100);

  human_t *p_lee = human_init(p_lee_mem, "lee", 100);

  3.4访问对象

  对象实例化后便存于内存中,此时可以访问对象的属性和方法,下面的代码展示了对象的访问:

  #include "human.h"

  void foo (void)

  {

  human_t john;/* 定义对象内存 */

  p_john = human_init(&jhon, "John", 100);

  /* 初始化对象 */

  printf("Human %s is born!", p_john->name);

  /* 访问对象的属性 */

  human_talk(p_john, "I am hungry");

  /* 访问对象的方法 */

  human_deinit(&john)/* 对象解初始化 */

  }

  3.5销毁对象

  当对象不再使用时,便可销毁之。销毁对象与创建对象(实例化)的操作相反,首先对对象进行解初始化操作,然后再释放对象的内存。

  以Human类为例,首先调用human_deinit()完成对象的解初始化,接下来,如果是静态对象或栈对象就不用显式释放对象的内存,因为静态对象或栈对象有确定的生命周期;如果是调用malloc()等函数得到了动态对象,则必须调用free()等对应的函数释放对象的内存。下面的代码展示了各种对象的销毁:

  #include "human.h"

  human_tg_john;/* 静态对象 */

  statichuman_t__g_jen;/* 静态对象 */

  void foo (void)

  {

  static human_ts_jack;/* 静态对象 */

  human_t tom;/* 栈对象 */

  human_t*p_lee_mem= malloc(sizeof(*p_lee_mem));

  /* 动态对象 */

  // 实例化上面定义的静态对象、动态对象和栈对象

  human_t *p_john = human_init(&g_john, "john", 100);

  human_t *p_jen = human_init(&__g_jen, "jen", 100);

  human_t *p_jack = human_init(&s_jack, "jack", 100);

  human_t *p_tom = human_init(&tom, "tom", 100);

  human_t *p_lee = human_init(p_lee_mem, "lee", 100);

  /* 销毁对象 */

  human_deinit(p_john);

  human_deinit(p_jen);

  human_deinit(p_jack);

  human_deinit(p_tom);

  human_deinit(p_lee);

  free(p_lee_mem);

  /* 注意:需要用户释放动态申请的对象内存 */

  }

4结论

  本文通过使用C语言实现Human类的实例化,讨论了如何使用C语言来实现类的实例化。在C++等面向对象语言中对类做了原生的支持,使用new这类关键字即可实例化一个对象。尽管C语言并不支持new,但是通过对实例化过程的分析和拆分,也能实现实例化。

  参考文献

  [1] 百度. 百度百科/面向对象[EB/OL].(2016-08-08).http://baike.baidu.com/link?url=6XlXEOSlrKn87S7SJv4 UWSX7EjstoDVm wJ13OAod XUrUrnZkVg3ntPFir Ey5c6mqOb ZZOevQI6K3Ungq1Mq.



此内容为AET网站原创,未经授权禁止转载。