本文引用自http://imtx.cn,原文作者:TualatriX
这节是最为关键的一节了,关于GObject中,对象是如何建立并初始化和销毁的。看起来,GObject的对象机制比C++还复杂,它详细规定了非常细致的初始化结构和相关步骤。
原文:http://library.gnome.org/devel/gobject/2.14/gtype-instantiable-classed.html
一个以类来注册,并声明为可实例化的类型常常称作对象。GObject(定义在The GObject base class中)是最有名的一个可实例化的类了,其他相似的类都继承于这个基本类来进行开发,他们都基于下面所述的基本特征。
下面的例子告诉你怎样才可以在类型系统中注册这样一个基本的类。
typedef struct { GObject parent; /* instance members */ int field_a; } MamanBar; typedef struct { GObjectClass parent; /* class members */ void (*do_action_public_virtual) (MamanBar *self, guint8 i); void (*do_action_public_pure_virtual) (MamanBar *self, guint8 i); } MamanBarClass; #define MAMAN_BAR_TYPE (maman_bar_get_type ()) GType maman_bar_get_type (void) { static GType type = 0; if (type == 0) { static const GTypeInfo info = { sizeof (MamanBarClass), NULL, /* base_init */ NULL, /* base_finalize */ (GClassInitFunc) foo_class_init, NULL, /* class_finalize */ NULL, /* class_data */ sizeof (MamanBar), 0, /* n_preallocs */ (GInstanceInitFunc) NULL /* instance_init */ }; type = g_type_register_static (G_TYPE_OBJECT, "BarType", &info, 0); } return type; }
在调用maman_bar_get_type之前,名为BarType的继承于G_TYPE_OBJECT的类将在类型系统中被注册。
每个对象必须定义为两个结构:它的类结构和它的实例结构。所有的类结构的第一个成员必须是一个GTypeClass结构。所有的实例结构的第一个成员必须是GTypeInstance结构。下面显示了这些来自gtype.h的C类型的声明:
struct _GTypeClass { GType g_type; }; struct _GTypeInstance { GTypeClass *g_class; };
这些约束使得类型系统可以确保每个对象的实例(由指向该对象的实例结构的指针所标识) 的首字节指向该对象的类结构。
这个关系可以由下面的例子来很好的解释:让我们来看看这个继承于对象A的对象B。
/* A definitions */ typedef struct { GTypeInstance parent; int field_a; int field_b; } A; typedef struct { GTypeClass parent_class; void (*method_a) (void); void (*method_b) (void); } AClass; /* B definitions. */ typedef struct { A parent; int field_c; int field_d; } B; typedef struct { AClass parent_class; void (*method_c) (void); void (*method_d) (void); } BClass;
上述标准的C结构定义指示了这个C结构的第一个领域存储着类的结构。This means that the first field of an instance of an object B is A’s first field which in turn is GTypeInstance’s first field which in turn is g_class, a pointer to B’s class structure.
多亏了这些简单的条件,所以按下面的方法来就可能取得每个对象实例的类型:
B *b; b->parent.parent.g_class->g_type
或者,更快的:
B *b; ((GTypeInstance*)b)->g_class->g_type
初始化和销毁
实例化这些类型可以用g_type_create_instance来完成:
GTypeInstance* g_type_create_instance (GType type); void g_type_free_instance (GTypeInstance *instance);
g_type_create_instance将查找请求的类型所关联的类型信息结构。然后由用户声明的实例的大小和实例化策略(如果n_preallocs设置为一个非零值,类型系统将会把对象的实例结构分配在内存块上,而不将依次分配每个实例)将得到一个缓存来保存对象实例的结构。
如果实例是这个对象第一次创建的,那么类型系统必须创建一个类结构:它为其分配一个缓冲来保存这个对象的类结构并初始化它。它先用父类的类结构覆盖(如果没有父类,它将初始化为零),然后从最顶层的基本对象至最底层的对象调用base_class_initialization函数(GBaseInitFunc)。对象的类初始化函数(GClassInitFunc)被调用来完成类结构的初始化。最终,这个类的接口被初始化了(我们将在后面讨论接口初始化)。
一旦类型系统有一个指向初始化的类结构的指针,它设置对象的实例类指针指向对象的类结构并调用实例的初始化函数(GInstanceInitFunc),同样是从顶到底的顺序。
对象的实例的销毁非常简单,通过g_type_free_instance即可:实例结构被返回到实例池中,如果这是对象的还有一个而且是最后一个存活的实例,那么这个类即被摧毁。
类的销毁 (关于这个销毁的另一概念是GType的终结)的过程与初始化的刚好对称:接口先被销毁。然后,调用类终结函数class_finalize(ClassFinalizeFunc)。最终,将base_class_finalize(GBaseFinalizeFunc)从底至顶的调用,直到类结构被销毁。
很多读者已经明白了,基本的初始化/终结化过程与C++的构造/析构函数非常相似。实际上细节是非常不同的,千万不要被表现的相似所迷惑。特别是,大多数用户开始认识到GType中并不存在类似于C++的构造器(这实际上是一个方法列表,由对象实例来调用所有有继承关系的方法),它必须建立在由GType提供的特定的设施里。同样的,GType没有实例销毁机制。这是用户的职责,在现存的GType代码的顶端来实现正确的销毁(这就是GObject做的事情)。
举个例子,如果从A继承的对象B被实例化了,GType将只调用对象B的instance_init回调函数,而C++运行环境将先调用对象A的构造器,接着再是对象B。事实上,C++代码与GType的base_init和class_init回调是等同的,不过C++常常是不需要这些的,因为它并不能真的在运行时创建类型。
关于实例化和终结化的处理过程可以归纳如下:
Invocation time | Function Invoked | Function’s parameters |
---|---|---|
First call to g_type_create_instance for target type | type’s base_init function | On the inheritance tree of classes from fundamental type to target type. base_init is invoked once for each class structure. |
target type’s class_init function | On target type’s class structure | |
interface initialization, see the section called “Interface Initialization” | ||
Each call to g_type_create_instance for target type | target type’s instance_init function | On object’s instance |
Last call to g_type_free_instance for target type | interface destruction, see the section called “Interface Destruction” | |
target type’s class_finalize function | On target type’s class structure | |
type’s base_finalize function | On the inheritance tree of classes from fundamental type to target type. base_finalize is invoked once for each class structure. |