Board logo

标题: GObject对象系统(3) [打印本页]

作者: look_w    时间: 2018-4-21 13:23     标题: GObject对象系统(3)

对象的属性和方法对象实例所有的属性和方法一般都定义在对象的实例结构中,属性定义为变量或变量指针,而方法则定义为函数指针,如此,我们一定要定义函数为static类型,当为函数指针赋值时,才能有效。
对象的继承以下为继承自Boy对象的Man对象的实现,Man对象在Boy对象的基础上又增加了一个属性job和一个方法bye。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#ifndef __MAN_H__
#define __MAN_H__
#include "boy.h"
#define MAN_TYPE  (man_get_type())
#define MAN(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),MAN_TYPE,Man))
typedef struct _Man Man;
typedef struct _ManClass ManClass;
struct _Man {
    Boy parent;
    char *job;
    void (*bye)(void);
};
struct _ManClass {
    BoyClass parent_class;
};
GType man_get_type(void);
Man*  man_new(void);
gchar* man_get_gob(Man *man);
void  man_set_job(Man *man, gchar *job);
Man*  man_new_with_name_age_and_job(gchar *name, gint age, gchar *job);
void man_info(Man *man);
#endif //__MAN_H__
/* man.c */
#include "man.h"
static void man_bye(void);
static void man_init(Man *man);
static void man_class_init(Man *man);
GType man_get_type(void)
{
    static GType man_type = 0;
    if(!man_type)
    {
        static const GTypeInfo man_info = {
            sizeof(ManClass),
            NULL, NULL,
            (GClassInitFunc)man_class_init,
            NULL, NULL,
            sizeof(Man),
            0,
            (GInstanceInitFunc)man_init
        };
        man_type = g_type_register_static(BOY_TYPE, "Man", &man_info, 0);
    }
    return man_type;
}
static void man_init(Man *man)
{
    man->job = "none";
    man->bye = man_bye;
}
static void man_class_init(Man *man)
{
}
Man*  man_new(void)
{
    Man *man;
    man = g_object_new(MAN_TYPE, 0);
    return man;
}
gchar* man_get_gob(Man *man)
{
    return man->job;
}
void  man_set_job(Man *man, gchar *job)
{
    man->job = job;
}
Man*  man_new_with_name_age_and_job(gchar *name, gint age, gchar *job)
{
    Man *man;
    man = man_new();
    boy_set_name(BOY(man), name);
    boy_set_age(BOY(man), age);
    man_set_job(man, job);
    return man;
}
static void man_bye(void)
{
    g_print("Goodbye everyone !\n");
}
void man_info(Man *man)
{
    g_print("the man name is %s\n", BOY(man)->name);
    g_print("the man age is %d\n", BOY(man)->age);
    g_print("the man job is %s\n", man->job);
}




关键在于定义对象时将父对象实例定义为Boy,父类设定为BoyClass,在注册此对象时将其父对象类型设为BOY_TYPE,在设定对象属性时如用到父对象的属性要强制转换下,如取得对象的name属性,就必须用BOY(obj)->name,因为Man本身没有name属性,而其父对象Boy有,所以用BOY宏将其强制为Boy类型的对象。
测试我们定义的对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <glib.h>
#include "boy.h"
#include "man.h"
int main(int argc, char *argv[])
{
    Boy *tom, *peter;
    Man *green, *brown;
    g_type_init();//注意,初始化类型系统,必需
    tom = boy_new_with_name("Tom");
    tom->cry();
    boy_info(tom);
    peter = boy_new_with_name_and_age("Peter", 10);
    peter->cry();
    boy_info(peter);
    green = man_new();
    boy_set_name(BOY(green), "Green");
//设定Man对象的name属性用到其父对象Boy的方法
    boy_set_age(BOY(green), 28);
    man_set_job(green, "Doctor");
    green->bye();
    man_info(green);
    brown = man_new_with_name_age_and_job("Brown", 30, "Teacher");
    brown->bye();
    man_info(brown);
}
Makefile文件如下:
CC = gcc
all:
    $(CC) -c boy.c `pkg-config --cflags glib-2.0 gobject-2.0`
    $(CC) -c man.c `pkg-config --cflags glib-2.0 gobject-2.0`
    $(CC) -c main.c `pkg-config --cflags glib-2.0 gobject-2.0`
    $(CC) -o simple boy.o man.o main.o `pkg-config --libs glib-2.0 gobject-2.0`
执行make命令编译,编译结束后,执行./simple运行此测试程序,输出结果如下:
Message : A boy was born .
The Boy is crying ......
The Boy name is Tom
The Boy age is 0
Message : A boy was born .
The Boy is crying ......
The Boy name is Peter
The Boy age is 10
Goodbye everyone !
the man name is Green
the man age is 28
the man job is Doctor
Goodbye everyone !
the man name is Brown
the man age is 30
the man job is Teacher




Makefile中用到`pkg-config -cflags -libs gobject-2.0`,在GLIB中将线程(gthread),插件(gmoudle)和对象系统(gobject)这三个子系统区别对待,编译时要注意加入相应的参数。
本文只是概要的介绍了如何定义和实现GObject对象,GObject系统中还有很多相关内容,如:枚举和标识类型(Enumeration and flags types);Gboxed,是Gtype系统中注册一种封装为不透明的C语言结构类型的机制;许多对象用到的参数对象都是C结构类型,使用者不必了解其结构的内部定义,即不透明,GBoxed即是实现这一功能的机制;标准的参数和变量类型的定义(Standard Parameter and Value Types)等,它们都以C语言来开发,是深入了解和掌握GObject的关键。
透过以上代码实现,我们还可以看出,以GLIB为基础的GTK+/GNOME开发环境所具有的独特的编程风格和独到的开发思想。这一点在长期的编程实践中会体验得更深刻。
有了GObject系统这一基础,GTK+通过它将X窗口环境中的控件(Widget)巧妙的封装起来,这使开发LINUX平台上的GUI应用程序更方便,更快捷。
以上代码在Redhat 8.0 Linux平台,GLIB2.2.1环境下编译通过。




欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/) Powered by Discuz! 7.0.0