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

  杨韬

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

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

  关键词: C语言;面向对象;;继承

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

  引用格式:杨韬. 用C语言实现继承的研究[J].微型机与应用,2016,35(24):16-18.

  0引言

  物联网等应用的兴起,给嵌入式软件开发带来新的挑战,而传统的面向过程开发方法已经难以支撑这些复杂的应用。因此,有必要在嵌入式软件开发中引入面向对象、设计模式等优秀的软件开发方法。在C++等面向对象语言中对类做了原生的支持,提供了class这一数据类型,能够很自然地支持继承这一面向对象特性。尽管C语言并不支持class,但是能够通过一些特殊的处理来模拟继承,本文将讨论如何使用C语言来实现继承这一面向对象特性。

1基本概念[1]

  1.1类

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

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

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

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

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

  1.2继承

  在定义一个类的时候,可以在一个已经存在的类的基础上进行,新的类自动继承已存在类的公有属性和方法,在此基础上可以添加新的属性或方法,这种特性就是继承。被继承的类称作父类或基类,继承而得到的新类称作子类或派生类。通过继承可以使开发的软件具有扩展性,简化了类的创建工作量,提高了代码复用性。

 

001.jpg

  图1为类继承的UML图,图中定义了两个类,两个类用空心三角箭头连接,箭头指向的就是父类Human,箭尾就是子类Chinese。Chinese类继承了Human类,Chinese类自动拥有Human的公有属性和方法(即name、buy()和talk()),此外,Chinese类新添加了方法play_mahjong()。通俗点描述就是:中国人是人类,有名字,能够讲话和购物,除此之外,还能打麻将。

  继承分为单重继承和多重继承:子类只继承一个父类,称为单重继承,如图1所示;子类继承多个父类,称为多重继承,如图2所示。为了避免二义性,不推荐使用多重继承,本文只讨论单重继承。

002.jpg

2类的C语言实现

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

  程序清单1Human类C语言实现

  // human.h

  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语言实现

  3.1C语言不能实现严格的继承

  一种常见的用C语言实现继承的方法如下面的代码所示:

  /* 父类 /基类*/

  struct parent {

  int a;

  };

  /* 子类/派生类 */

  struct child {

  struct parent base; /* 第一个成员为基类 */

  int b;

  };

  void foo (void)

  {

  struct childfoo;

  struct child *p_child;

  struct parent*p_parent;

  p_child = &foo;

  p_parent = (struct parent *)p_child;

  /* 将子类转换为父类 */

  p_parent->a = 100;/* 访问父类成员 */

  }

  上面的代码中定义了一个父类和子类,foo()函数中实例化了一个子类对象,使用强制类型转换将子类对象的指针p_child转换为父类指针p_parent,如此达到了访问其父类成员的效果。此方法有明显的缺陷——使用了强制类型转换,而在C语言编程中是要避免使用强制类型转换的。如果要得到子类的父类,推荐下面这种更安全的方法:

  p_parent = &p_child->base;

  对于很多面向对象编程语言来说,子类对象调用父类的属性方法不需要显式转型,而C语言做不到这一点,比如,不能通过p_child->a直接访问父类的属性,因此,严格意义上说“C语言不能实现严格的继承”。

  3.2用C语言实现继承

  在前面一节中指出“C语言不能实现严格的继承”,尽管如此,由于继承在软件设计中时有使用,因此用C语言实现继承仍是必要的。尽管继承实现的效果不如C++等面向对象语言那么完美,但还是可以达到实用程度的。

  以图1为例,Human为父类,Chinese为基类。Human类的实现请参考程序清单1,Chinese类的实现(chinese.h)请参考程序清单2,chinese.c为chinese.h中函数声明的实现,本文不讨论这些细节。

  程序清单2Chinese类C语言实现

  #include "human.h"

  typedef struct chinese {

  human_t super;

  const char *city;

  } chinese_t;

  #define CHINESE_TO_HUMAN(p_chinese) \  (&((p_chinese)->super))

  chinese_t *chinese_init (chinese_t *p_this, const char *name, int money, const char *city);

  chinese_t *chinese_create(const char *name, unsigned int money, const char *city);

  void chinese_play_mahjong (chinese_t *p_this);

  void chinese_deinit (chinese_t *p_this);

  void chinese_delete (chinese_t **pp_this);

  Chinese类继承Human类体现在struct chinese 结构体中嵌入了其父类struct human成员,但这并不是完美的继承,如果要访问父类的属性和方法,需要先调用CHINESE_TO_HUMAN()将子类指针转型为父类指针。需要注意的是CHINESE_TO_HUMAN()并没有使用强制类型转换,这意味着struct chinese的成员super可以放在任意位置,大大提高了使用的安全性和灵活性。程序清单3展示了继承相关特性的使用。

  程序清单3继承的使用

  chinese_txiaoming, *p_xiaoming;

  human_t*p_human;

  p_ xiaoming = chinese_create(

  "XiaoMing", 100, "Beijing"); // 实例化子类

  p_human = CHINESE_TO_HUMAN(p_ xiaoming);

  // 向上转型,得到父类引用

  human_talk(p_human, "Ni Hao!\\n");// 调用父类方法

  chinese_play_mahjong(p_laowang);// 调用子类方法

4结论

  本文通过使用C语言实现Chinese类对Human类的继承,讨论了如何使用C语言来实现继承。在C++等面向对象语言中对类做了原生的支持,能够很容易地实现。尽管C语言不能实现严格意义上的继承,但是通过在一个结构体中嵌入另一个结构体的方式,也能达到继承的效果,与其他面向对象语言不同的是,调用父类方法时需要显式转型。

参考文献

  [1] 百度百科. 面向对象[EB/OL].(2012 12 12)[2016 08 08]http://baike.baidu.com/linkurl=6XlXEOSlrKn87S7SJv4U WSX7EjstoDVmwJ13OAodXUrUrnZkVg3ntPFirEy5c6mqObZZ OevQI6K3Ungq1Mq.

  

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