glib实践篇:父类与子类
前言:
众所周知,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语言来支持
。
glib实践篇:父类与子类的更多相关文章
- Java特性之多态父类与子类之间的调用
问题描述: Java三大特性,封装.继承.多态,一直没搞懂其中多态是什么,最近研究了一下,关于父类和子类之间的调用.下面是一个测试类,源代码如下: package com.test; public c ...
- java中父类与子类, 不同的两个类中的因为构造函数由于递归调用导致栈溢出问题
/* 对于类中对成员变量的初始化和代码块中的代码全部都挪到了构造函数中, 并且是按照java源文件的初始化顺序依次对成员变量进行初始化的,而原构造函数中的代码则移到了构造函数的最后执行 */ impo ...
- java父类转子类的一个方法
一般子类可以转父类.但父类转子类就会报cast error. 使用jsonobject 思想:先把父类转jsonstring 再把jsonstring转子类.剩余的子类值可以设定进去. import ...
- P188 实战练习(父类和子类)
1.创建一个父类,在父类中创建两个方法,在子类中覆盖第二个方法,为子类创建一个对象,将它向上转型到基类并调用这个方法. 创建Computer父类: package org.hanqi.practise ...
- 20141214--C#父类,子类
首要: 子类 包含父类的所有的属性方法 所有子类都可以直接转化成父类类型 当父类类型变量里面存的是某个子类的对象的时候,才能转化成那个子类类型. 父类与子类的装换: Ren r = new Ren() ...
- 多态&&父类调用子类特有的方法
/* 多态 1.没有继承就没有多态 2.代码的体现:父类类型的指针指向子类对象 3.好处:如果函数\方法参数使用的是父类对象,可以传入父类.子类对象 4.局限性: 1>父类类型的变量,不能直接调 ...
- C#基础知识—父类和子类的关系
基础知识一: using System; using System.Collections.Generic; using System.Linq; using System.Windows.Forms ...
- php 父类调用子类方法和成员
在C和C++里,父类都不允许调用子类的方法,但在php里可以.下面是一个调用的例子: <?php abstract class Animal { protected $name; public ...
- Java 多态 父类和子类方法的访问控制权限
Java 多态 父类和子类方法的访问控制权限 @author ixenos 父类和子类方法的访问控制权限 继承是为了扩展类的功能,而这种扩展显然就是对一个原始类的扩展,目的还是向上转型来调用,所以这就 ...
- c++ --> 父类与子类间的继承关系
父类与子类间的继承关系 一.父类与子类 父类与子类的相互转换 1.派生类的对象可以赋给基类,反之不行 2.基类的指针可以指向派生类,反之不行 3.基类的引用可以初始化为派生类的对象,反之不行 4.派生 ...
随机推荐
- TodoList开发笔记 – PartⅠ
做了一年多的桌面软件,最近开始转向Web方面的开发,既然比较熟悉Net那么首当其冲就是学习ASP.Net,以及HTML.CSS.Javascript. 为了检验这个把星期来的学习成果,着手做了一个To ...
- 在MVC中使用SignalR
在MVC中使用SignalR 接着上一篇:<ASP.NET SignalR系列>第四课 SignalR自托管(不用IIS) 一.概述 本教程主要阐释了如何在MVC下使用ASP.NET Si ...
- Ubuntu中的.bashrc文件
/etc/profile:此文件为系统的每个用户设置环境信息,当用户第一次登录时,该文件被执行.并从/etc/profile.d目录的配置文件中搜集shell的设置./etc/bashrc:为每一个运 ...
- Remote验证及其改进(附源码)
Remote验证及其改进(附源码) 表单中的输入项,有些是固定的,不变的验证规则,比如字符长度,必填等.但有些是动态的,比如注册用户名是否存在这样的检查,这个需要访问服务器后台才能解决.这篇文章将会介 ...
- 在 go/golang语言中使用 google Protocol Buffer
怎么在go语言中实用google protocol Buffer呢? 现在的潮流趋势就是一键搞定,跟ubuntu安装软件一样 go get code.google.com/p/goprotobuf/{ ...
- C#通过接口与线程通信(捕获线程状态)介绍
C#通过接口与线程通信(捕获线程状态)介绍 摘要:本文介绍C#通过接口与线程通信(捕获线程状态),并提供简单的示例代码供参考. 提示:本文所提到的线程状态变化,并不是指线程启动.暂停.停止,而是说线程 ...
- SAX解析xml浅析
SAX解析XML文件采用事件驱动的方式进行,也就是说,SAX是逐行扫描文件,遇到符合条件的设定条件后就会触发特定的事件,回调你写好的事件处理程序.使用SAX的优势在于其解析速度较快,占用内存较少(相对 ...
- poj1837挂砝码
解法(背包DP问题) (下为转) 其实感觉 像此题这种类型的并不属于dp范畴 虽然程序看起来使用的是递推这一过程,但总不能说开个二重循环就是dp吧 如果只从求解上来讲(不考虑数据值的范围), 只有枚举 ...
- 迟到的 WPF 学习 —— 布局
布局是 WPF 很重头的一部分内容,这一部分梳理和记录关于布局章节的知识点. 1. WPF 使用一种基于流(Flow-based)的概念来处理布局逻辑,将传统的基于"坐标"的思想尽 ...
- 程序处理数据库中值字段值为null的查询显示
1.如果你做了一个简单的注册界面,需要用户进行注册,但有些项是不必要填的,当用户完成注册时,数据库表中的相应字段的值会写入null,但如何将查询的字段的值null显示出来? 2.首先我们学习一下如何向 ...