gobject创建一个新的实例(继承和重构)

概述

在 GObject世界里,类是两个结构体的组合,一个是实例结构体,另一个是类结构体。GOBJECT的继承需要实现实例结构体的继承和类结构体的继承,Gobject对象的初始化可分为两个部分:类结构体初始化和实例结构体初始化。类结构体初始化函数只被调用一次,而实例结构体的初始化函数的调用次数等于对象实例化的次数。这意味着,所有对象共享的数据,可保存在类结构体中,而所有对象私有的数据,则保存在实例结构体中。

宏定义解析G_DEFINE_TYPE

G_DEFINE_TYPE(Man, man, G_TYPE_OBJECT);

参数1 Man:注册新的类名称(与结构体同名)。
参数2 man:注册新类初始化函数前缀,比如shape_init(man *shape)。这里填写什么字符串(假设为:XXX),就要实现XXX_init,XXX_class_init,XXX_get_type。
参数3 G_TYPE_OBJECT:父类的类型,这里表示man的父类是OBJECT。其实就是对应父类的XXX_get_type。

定义一个新的类,最少要实现三个函数

/* 类结构 */
typedef struct _mytest {
	int member1;
	char member2;
	void (*func)(void);
	/*  略 */
} Mytest;

//对象初始化函数
void mytest_init(Mytest *arg);
//类的初始化函数
void mytest_class_init(MytestClass *class);
//该函数实现向GObject注册我们新定义的mytest类,可通过G_DEFINE_TYPE进行实现。
Gtype mytest_get_type(void);

第一个函数是实例结构体初始化,第二个是类结构体初始化,第三个是实现向GObject注册我们新定义的mytest类,可通过G_DEFINE_TYPE进行实现。

Demo实现了Man类Teacher类,Teacher类继承了Man类,并且重载了Man类的info()函数

man.h

#ifndef _MAN_H_
#define _MAN_H_

#include <glib-object.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;

//实例结构体,结构体的首元素类型必须是Gobject
struct _Man{
    GObject parent;
    gchar* name;
    int age;
    void (*info) (void);
    int (*SetAge)(Man *man,int age);
    int (*GetAge)(Man *man);
};

//类结构体,结构体的首元素必须是GObjectClass
struct _ManClass{
    GObjectClass parent_class; 
};



//被宏定义的函数在这里声明
GType man_get_type(void);

void info_func(void);
int set_age(Man *man,int age);
int get_age(Man *man);





#endif

man.c

#include "man.h"
#include <glib.h>

//这里必须要
G_DEFINE_TYPE(Man, man, G_TYPE_OBJECT);

void info_func(void)
{
    g_print("This is man info func\n");
}


static void man_init(Man* man)
{
    man->age = 0;
    man->name = "";
    man->info = info_func;
    man->SetAge = set_age; 
    man->GetAge = get_age;
    g_print("This is man_init func\n");
}

static void man_class_init(ManClass* manClass)
{
    g_print("This is man_class_init func\n");
}

int set_age(Man *man,int age)
{
    man->age = age;
    return 0;
}

int get_age(Man *man)
{
    return man->age;
}

teacher.h

#ifndef _TEACHER_H_
#define _TEACHER_H_


#include "man.h"
//宏定义这个函数
#define TEACHER_TYPE (teacher_get_type())

typedef struct _Teacher Teacher;
typedef struct _TeacherClass TeacherClass; 


//结构体的第一个元素是Man
struct _Teacher{
    Man parent;
    gint salary;
    gchar* duty;
    gchar* (*GetDuty)(Teacher*);
};
//结构体的第一个元素是ManClass
struct _TeacherClass{
    ManClass parent_class;
};

void teacher_info(void);
//被宏定义的函数在这里声明
GType teacher_get_type(void);
gchar* get_duty(Teacher* tea);


#endif

teacher.c

#include "teacher.h"


//这里必须要
G_DEFINE_TYPE(Teacher, teacher, MAN_TYPE);





static void teacher_init(Teacher* tea)
{
    Man* man = MAN(tea);
    man->name = "man"; 
    man->age = 12;
    //重构info函数
    man->info = teacher_info;
    

    tea->salary = 10000;
    tea->duty = "jiangshi";
    tea->GetDuty = get_duty;
}

static void teacher_class_init(TeacherClass* TeacherClass)
{
    g_print("%s\n",__func__);
}

void teacher_info(void)
{
    g_print("%s\n",__func__);
}

gchar* get_duty(Teacher* tea)
{
    return tea->duty;
}

main.c

#include "man.h"
#include "teacher.h"
#include <glib.h>

int main(void)
{
    Man* man1 = NULL;
    //创建一个对象并返回对象的指针
    man1 = g_object_new(MAN_TYPE, NULL);
    man1->info();
    man1->SetAge(man1,19);
    g_print("man1->age = %d\n",man1->GetAge(man1));
    //销毁对象
    g_object_unref(man1);
    
    Teacher* tea = NULL;
    tea = g_object_new(TEACHER_TYPE, NULL);
    //info函数被重构
    MAN(tea)->info();
    g_print("tea->duty=%s\n",tea->GetDuty(tea));
    g_object_unref(tea);


    return 0;
}

运行结果

root@ubuntu:/code/test/ManObject# gcc *.c `pkg-config --cflags --libs glib-2.0 gobject-2.0`
root@ubuntu:/code/test/ManObject# ./a.out
This is man_class_init func
This is man_init func
This is man info func
man1->age = 19
teacher_class_init
This is man_init func
teacher_info
tea->duty=jiangshi
root@ubuntu:/code/test/ManObject#

总结

到最后,其实可以抛开复杂的底层实现,简单的归纳为下面几点:
1、在.h中加入头文件#include <glib-object.h>;
2、在.h中定义实例结构体和类结构体;
3、在.h中写宏定义#define XXX_TYPE (xxx_get_type());
4、在.h中声明xxx_get_type()函数
5、在.c中使用宏定义G_DEFINE_TYPE;
6、在.c中定义xxx_init()函数和xxx_class_init()函数
7、如果这个类要作为父类,则还需要在.h宏定义#define XXX(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), XXX_TYPE, 实例名))

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章