zoukankan      html  css  js  c++  java
  • GObject对象系统 (1)


          简单的说,GObject对象系统是一个建立在GLIB基础上的,用C语言完成的,具有跨平台特色的、灵活的、可扩展的、

    非常容易映射到其它语言的面向对象的框架。如果你是一个C语言的执着的追随者,你没有理由不研究一下它。
    前言

    大多数现代的计算机语言都带有自己的类型和对象系统,并附带算法结构。正象GLib提供的基本类型和算法结构(如链表、哈希表等)一样,GObject的对象系统提供了一种灵活的、可扩展的、并容易映射(到其它语言)的面向对象的C语言框架。它的实质可以概括为:

        * 一个通用类型系统,用来注册任意的、轻便的、单根继承的、并能推导出任意深度的结构类型的界面,它照顾组合对象的定制、初始化和内存管理,类结构,保持对象的父子关系,处理这些类型的动态实现。也就是说,这些类型的实现是在运行时重置和卸载的;
        * 一个基本类型的实现集,如整型,枚举型和结构型等;
        * 一个基本对象体系之上的基本对象类型的实现的例子--GObject基本类型;
        * 一个信号系统,允许用户非常灵活的自定义虚的或重载对象的方法,并且能充当非常有效力的通知机制;
        * 一个可扩展的参数/变量体系,支持所有的能被用作处理对象属性或其它参数化类型的基本的类型。

    类型(GType)与对象(GObject)

    GLib中最有特色的是它的对象系统--GObject System,它是以Gtype为基础而实现的一套单根继承的C语言的面向对象的框架。

    GType 是GLib 运行时类型认证和管理系统。GType API 是GObject的基础系统,所以理解GType是理解GObject的关键。Gtype提供了注册和管理所有基本数据类型、用户定义对象和界面类型的技术实现。(注意:在运用任一GType和GObject函数之前必需运行g_type_init()函数来初始化类型系统。)

    为实现类型定制和注册这一目的,所有类型必需是静态的或动态的这二者之一。静态的类型永远不能在运行时加载或卸载,而动态的类型则可以。静态类型由 g_type_register_static()创建,通过GTypeInfo结构来取得类型的特殊信息。动态类型则由 g_type_register_dynamic()创建,用GTypePlugin结构来取代GTypeInfo,并且还包括 g_type_plugin_*()系列API。这些注册函数通常只运行一次,目的是取得它们返回的专有类的类型标识。

    还可以用g_type_register_fundamental来注册基础类型,它同时需要GTypeInfo和GTypeFundamentalInfo两个结构,事实上大多数情况下这是不必要的,因为系统预先定义的基础类型是优于用户自定义的。

    (本文重点介绍创建和使用静态的类型。)
    对象的定义

    在GObject系统中,对象由三个部分组成:

       1. 对象的ID标识(唯一,无符号长整型,所有此类对象共同的标识);
       2. 对象的类结构(唯一,结构型,由对象的所有实例共同拥有);
       3. 对象的实例(多个,结构型,对象的具体实现)。

    基于GObject的对象到底是什么样的呢?下面是基于GObject的简单对象 -- Boy的定义代码:

    /* boy.h */

    #ifndef __BOY_H__
    #define __BOY_H__

    #include <glib-object.h>

    #define BOY_TYPE (boy_get_type())

    #define BOY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),BOY_TYPE,Boy))

    typedef struct _Boy Boy;
    typedef struct _BoyClass BoyClass;

    struct _Boy {
    GObject parent;

    gint age;
    gchar *name;
    void (*cry)(void);
    };

    struct _BoyClass {
    GObjectClass parent_class;

    void (*boy_born)(void);
    };

    GType    boy_get_type(void);

    Boy*  boy_new(void);

    int    boy_get_age(Boy *boy);

    void    boy_set_age(Boy *boy, int age);

    char* boy_get_name(Boy *boy);

    void    boy_set_name(Boy *boy, char *name);

    Boy*  boy_new_with_name(gchar *name);

    Boy*  boy_new_with_age(gint age);

    Boy*  boy_new_with_name_and_age(gchar *name, gint age);

    void  boy_info(Boy *boy);

    #endif /* __BOY_H__*/

    这是一段典型的C语言头文件定义,包括编译预处理,宏定义,数据结构定义和函数声明;首先要看的是两个数据结构对象Boy和BoyClass,

    结构类型_Boy是Boy对象的实例,就是说我们每创建一个Boy对象,也就同时创建了一个Boy结构。Boy对象中的parent表示此对象的父类,

    GObject系统中所有对象的共同的根都是GObject类,所以这是必须的;其它的成员可以是公共的,这里包括表示年龄的age,

    表示名字的name和表示方法的函数指针cry,外部代码可以操作或引用它们。

    结构类型_BoyClass是Boy对象的类结构,它是所有Boy对象实例所共有的。BoyClass中的parent_class是GObjectClass,

    同GObject是所有对象的共有的根一样,GObejctClass是所有对象的类结构的根。在BoyClass中我们还定义了一个函数指针boy_born,

    也就是说这一函数指针也是所有Boy对象实例共有的,所有的Boy实例都可以调用它;同样,如果需要的话,你也可以在类结构中定义其它数据成员。

    其余的函数定义包括三种,

    一种是取得Boy对象的类型ID的函数boy_get_type,这是必须有的;

    另一种是创建Boy对象实例的函数boy_new和boy_new_with_*,这是非常清晰明了的创建对象的方式,

    当然你也可以用g_object_new函数来创建对象;

    第三种是设定或取得Boy对象属性成员的值的函数boy_get_*和boy_set_*。

    正常情况下这三种函数都是一个对象所必需的,另外一个函数boy_info用来显示此对象的当前状态。

    宏在GObject系统中用得相当广泛,也相当重要,这里我们定义了两个非常关键的宏,BOY_TYPE宏封装了boy_get_type函数,

    可以直接取得并替代Boy对象的ID标识;

    BOY(obj)宏是G_TYPE_CHECK_INSTANCE_CAST宏的再一次封装,目的是将一个Gobject对象强制转换为Boy对象,

    这在对象的继承中十分关键,也经常用到。

  • 相关阅读:
    DP(动态规划)学习心得
    hloj#402 护卫队解题讨论
    hloj#168“倒牛奶”解题讨论
    贪心:畜栏预定
    区间问题
    离散化
    差分
    浏览器的工作原理幕后揭秘的部分笔迹摘要
    python之阶乘的小例子
    关于python中urllib.urlencode的时候出错:UnicodeEncodeError: ‘ascii’的记录
  • 原文地址:https://www.cnblogs.com/zhangze/p/1741131.html
Copyright © 2011-2022 走看看