前言:
众所周知,C语言是一门面向过程的语言,但是不代表就得跟面向对象完全绝缘,在C语言库glib中有gobject那么一套面向对象的机制,基于C语言的面向对象设计便是基于该实现机制。
今天所要实践的便是面向对象的一个重要特征:抽象与继承
笔者的水平有限,如果文章有什么错误的地方还望指出。
1、设计说明
开发语言:C语言
基础库:glib
设计目的:简要设计类来实现抽象与继承
2、由几个有相同属性或操作的类抽象出一个父类。
这里简单使用gobject的一套设计模板,细节部分不做说明,有研究兴趣的读者可以研究一下。
父类:base(该类由base.h和base.c共同组成)
base.h
#ifndef __BASE_H__
#define __BASE_H__ #include <glib.h>
#include <stdio.h>
#include <glib-object.h>
G_BEGIN_DECLS #define BASE_TYPE (base_get_type ())//该对象的类型
#define BASE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), BASE_TYPE, Base))//类型转换,转换为该对象的类型
#define BASE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), BASE_TYPE, BaseClass))
#define IS_BASE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), BASE_TYPE))
#define IS_BASE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), BASE_TYPE))
#define BASE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), BASE_TYPE, BaseClass))
#define BASE_CAST(obj) ((Base*)(obj)) typedef struct _Base Base;
typedef struct _BaseClass BaseClass;
typedef struct _BasePrivate BasePrivate; struct _Base
{
GObject parent;
//设置共有变量,提供给子类访问
GString *str;
}; struct _BaseClass
{
GObjectClass parentclass;
//设置设置写和读名字的方法,由子类重载
void (*showKill)(Base *self);
char *(*getSkill)(Base *self);
}; GType base_get_type (void);
//这些方法被子类所共有,其中skill的操作方法需要由子类重载。
void base_set_name(Base *self,char *name);
char * base_get_name(Base *self);
void base_show_skill(Base *self);
char * base_get_skill(Base *self); G_END_DECLS #endif /* ABSTRACTMODEL_H_ */
basec.c
#include "base.h"
#include <string.h> //父类即抽象类的宏定义,继承自object
G_DEFINE_ABSTRACT_TYPE(Base, base, G_TYPE_OBJECT); #define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), BASE_TYPE, Base)) struct _BasePrivate
{
char *name;
}; static void dispose_od(GObject *object);
static void finalize_od(GObject *object); static void base_class_init(BaseClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS(klass);
g_type_class_add_private(klass, sizeof(BasePrivate));
object_class->dispose = dispose_od;
object_class->finalize = finalize_od;
} static void base_init(Base *self)
{
BasePrivate *priv = GET_PRIVATE(self);
self->str = g_string_new("暴露出来给你们访问的");
}
static void dispose_od(GObject *object)
{
Base *self = BASE(object);
BasePrivate *priv = GET_PRIVATE(self);
if(self->str)
{
g_string_free(self->str,TRUE);
self->str=NULL;
}
G_OBJECT_CLASS(base_parent_class)->dispose(object);
} static void finalize_od(GObject *object)
{
Base *self = BASE(object);
BasePrivate *priv = GET_PRIVATE(self); G_OBJECT_CLASS(base_parent_class)->finalize(object);
} void base_set_name(Base *self,char *name)
{
BasePrivate *priv = GET_PRIVATE(self);
priv->name = strdup(name);
}
char *base_get_name(Base *self)
{
BasePrivate *priv = GET_PRIVATE(self);
return priv->name;
} void base_show_skill(Base *self)
{
if (self)
{
BaseClass *baseClass = BASE_GET_CLASS(self);
baseClass->showKill(self);
}
}
char * base_get_skill(Base *self)
{
char *skill = NULL;
if (self)
{
BaseClass *baseClass = BASE_GET_CLASS(self);
skill = baseClass->getSkill(self);
}
return skill;
}
子类1:(由文件subbase1.h和subbase.c组成)
subbase1.h
#ifndef __SUBBASE1_H__
#define __SUBBASE1_H__ #include <glib.h>
#include <stdio.h>
#include <glib-object.h>
#include"base.h"
G_BEGIN_DECLS #define SUBBASE1_TYPE (subbase1_get_type ())//该对象的类型
#define SUBBASE1(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), SUBBASE1_TYPE, Subbase1))//类型转换,转换为该对象的类型
#define SUBBASE1_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), SUBBASE1_TYPE, Subbase1Class))
#define IS_SUBBASE1(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), SUBBASE1_TYPE))
#define IS_SUBBASE1_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), SUBBASE1_TYPE))
#define SUBBASE1_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), SUBBASE1_TYPE, Subbase1Class))
#define SUBBASE1_CAST(obj) ((Subbase1*)(obj)) typedef struct _Subbase1 Subbase1;
typedef struct _Subbase1Class Subbase1Class;
typedef struct _Subbase1Private Subbase1Private; struct _Subbase1
{
Base parent;
}; struct _Subbase1Class
{
BaseClass parentclass;
}; GType subbase1_get_type (void);
Subbase1* subbase1_new(void);
void subbase1_sing_song(Subbase1 *self,char *song); G_END_DECLS
#endif /* ABSTRACTMODEL_H_ */
subbase1.c
#include "subbase1.h"
#include <string.h> //子类的宏定义,继承父类类型
G_DEFINE_TYPE(Subbase1, subbase1, BASE_TYPE); #define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SUBBASE1_TYPE, Subbase1)) struct _Subbase1Private
{
}; static void dispose_od(GObject *object);
static void finalize_od(GObject *object);
static char *getSkill_od(Base *self);
static void showKill_od(Base *self);
static void subbase1_class_init(Subbase1Class *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS(klass);
g_type_class_add_private(klass, sizeof(Subbase1Private));
object_class->dispose = dispose_od;
object_class->finalize = finalize_od;
BaseClass *baseClass = BASE_CLASS(klass);
baseClass->getSkill =getSkill_od;
baseClass->showKill = showKill_od; } static void subbase1_init(Subbase1 *self)
{
Subbase1Private *priv = GET_PRIVATE(self);
}
static void dispose_od(GObject *object)
{
Subbase1 *self = SUBBASE1(object);
Subbase1Private *priv = GET_PRIVATE(self); G_OBJECT_CLASS(subbase1_parent_class)->dispose(object);
} static void finalize_od(GObject *object)
{
Subbase1 *self = SUBBASE1(object);
Subbase1Private *priv = GET_PRIVATE(self); G_OBJECT_CLASS(subbase1_parent_class)->finalize(object);
}
static char *getSkill_od(Base *self)
{
return "sing";
}
static void showKill_od(Base *self)
{
g_print("I singing!\n");
} Subbase1* subbase1_new(void)
{
Subbase1 *res = g_object_new(SUBBASE1_TYPE,NULL);
return res; }
void subbase1_sing_song(Subbase1 *self,char *song)
{
g_print("I singing a song for name is %s!\n",song);
}
子类2:(由subbase2.h和subbase2.c文件组成)
subbase2.h
#ifndef __SUBBASE2_H__
#define __SUBBASE2_H__ #include <glib.h>
#include <stdio.h>
#include <glib-object.h>
#include"base.h"
G_BEGIN_DECLS #define SUBBASE2_TYPE (subbase2_get_type ())//该对象的类型
#define SUBBASE2(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), SUBBASE2_TYPE, Subbase2))//类型转换,转换为该对象的类型
#define SUBBASE2_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), SUBBASE2_TYPE, Subbase2Class))
#define IS_SUBBASE2(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), SUBBASE2_TYPE))
#define IS_SUBBASE2_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), SUBBASE2_TYPE))
#define SUBBASE2_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), SUBBASE2_TYPE, Subbase2Class))
#define SUBBASE2_CAST(obj) ((Subbase2*)(obj)) typedef struct _Subbase2 Subbase2;
typedef struct _Subbase2Class Subbase2Class;
typedef struct _Subbase2Private Subbase2Private; struct _Subbase2
{
Base parent;
}; struct _Subbase2Class
{
BaseClass parentclass;
}; GType subbase2_get_type (void);
Subbase2 * subbase2_new(void);
void subbase2_dance_dance(Subbase2 *self,char *dance); G_END_DECLS
#endif /* ABSTRACTMODEL_H_ */
subbase2.c
#include "subbase2.h"
#include <string.h> //子类的宏定义,继承父类类型
G_DEFINE_TYPE(Subbase2, subbase2, BASE_TYPE); #define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SUBBASE2_TYPE, Subbase2)) struct _Subbase2Private
{
}; static void dispose_od(GObject *object);
static void finalize_od(GObject *object);
static void showSkill_od(Base *self);
static char *getSkill_od(Base *self); static void subbase2_class_init(Subbase2Class *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS(klass);
g_type_class_add_private(klass, sizeof(Subbase2Private));
object_class->dispose = dispose_od;
object_class->finalize = finalize_od;
BaseClass *baseClass = BASE_CLASS(klass);
baseClass->getSkill=getSkill_od;
baseClass->showKill=showSkill_od;
} static void subbase2_init(Subbase2 *self)
{
Subbase2Private *priv = GET_PRIVATE(self);
} static void dispose_od(GObject *object)
{
Subbase2 *self = SUBBASE2(object);
Subbase2Private *priv = GET_PRIVATE(self); G_OBJECT_CLASS(subbase2_parent_class)->dispose(object);
} static void finalize_od(GObject *object)
{
Subbase2 *self = SUBBASE2(object);
Subbase2Private *priv = GET_PRIVATE(self); G_OBJECT_CLASS(subbase2_parent_class)->finalize(object);
}
static void showSkill_od(Base *self)
{
g_print("I ' m dancing\n");
}
static char *getSkill_od(Base *self)
{
return "dance";
} Subbase2 * subbase2_new(void)
{
Subbase2 *res = g_object_new(SUBBASE2_TYPE,NULL);
return res;
}
void subbase2_dance_dance(Subbase2 *self,char *dance)
{
g_print("I ' m dancing a %s dance!\n",dance);
}
测试文件:main.c
#include<glib.h>
#include<stdio.h>
#include<stdlib.h>
#include"base.h"
#include"subbase1.h"
#include"subbase2.h"
#include<string.h> int main(void)
{
g_print("hell world!\n");
Subbase1 *test1 = subbase1_new();
Subbase1 *test2 = subbase1_new();
Subbase2 *test3 = subbase2_new(); base_set_name(BASE(test1),"test1");
base_set_name(BASE(test2),"test2");
base_set_name(BASE(test3),"test3"); g_print("name:%s\n",base_get_name(BASE(test1)));
g_print("name:%s\n",base_get_name(BASE(test2)));
g_print("name:%s\n",base_get_name(BASE(test3))); g_print("skill:%s\n",base_get_skill(BASE(test1)));
base_show_skill(BASE(test1));
g_print("skill:%s\n", base_get_skill(BASE(test3)));
base_show_skill(BASE(test3)); subbase1_sing_song(test1,"我怀恋的");
subbase2_dance_dance(test3,"芭蕾"); BASE(test1)->str = g_string_new("one");
g_print("%s\n",BASE(test1)->str->str); return EXIT_SUCCESS;
}
3、总结
如2的代码所示,其中涉及到了抽象、继承、重载等概念,C语言要使用面向对象来设计和解决问题,那么关于面向对象一般的基本特征也要了解和实现,要充分将这些实现方式转化为经验,这样再以后的面向对象设计中才能
驾轻就熟,也会更有效率。
同时如大家所见,C语言要实现面向对象这一特征是较为复杂的,代码相对JAVA或python等也非常的多,但是在嵌入式或一些需要使用C语言来设计和解决问题的领域,使用面向对象设计是有着很大的好处的,其中最明显的就是
可以减轻设计的复杂度。
4、题外话
在嵌入式领域C++的比重越来越来越大,著名的QT、openCV(一部分)等都是由C语言开发,C++开发嵌入式应用的效率上是有优势的,但是大部分的底层库还是得由C语言来实现,尤其是一些核心的东西需要C语言来支持
。