GObject is a fundamental classed instantiable type. It implements:
-
Memory management with reference counting
-
Construction/Destruction of instances
-
Generic per-object properties with set/get function pairs
-
Easy use of signals
Object instantiation 对象实例化
The g_object_new
family of functions can be used to instantiate any GType which inherits from the GObject base type. All these functions make sure the class and instance structures have been correctly initialized by GLib's type system and then invoke at one point or another the constructor class method which is used to:
-
Allocate and clear memory through
g_type_create_instance
, -
Initialize the object's instance with the construction properties.
Although one can expect all class and instance members (except the fields pointing to the parents) to be set to zero, some consider it good practice to explicitly set them.
Once all construction operations have been completed and constructor properties set, the constructed class method is called.
Objects which inherit from GObject are allowed to override this constructed class method. The example below shows how ViewerFile overrides the parent's construction process:
尽管开发者可以假设除了指向父类的域外其他所有类结构和实例结构的成员被设置为0,但在需要的时候开发者最好显式地设置它们。
一旦所有的构造操作已经完成并且构造属性已经被设置,类构造方法将被调用。
从GObject继承而来的对象可以重写类构造方法,以下代码展示了ViewerFile重写父类构造方法的过程:
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 | #define VIEWER_TYPE_FILE viewer_file_get_type () G_DECLARE_FINAL_TYPE (ViewerFile, viewer_file, VIEWER, FILE, GObject) struct _ViewerFile { GObject parent_instance; /* instance members */ }; /* will create viewer_file_get_type and set viewer_file_parent_class */ G_DEFINE_TYPE (ViewerFile, viewer_file, G_TYPE_OBJECT) static void viewer_file_constructed (GObject *obj) { /* update the object state depending on constructor properties */ /* Always chain up to the parent constructed function to complete object * initialisation. */ G_OBJECT_CLASS (viewer_file_parent_class)->constructed (obj); } static void viewer_file_class_init (ViewerFileClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->constructed = viewer_file_constructed; } static void viewer_file_init (ViewerFile *self) { /* initialize the object */ } |
1 | ViewerFile *file = g_object_new (VIEWER_TYPE_FILE, NULL); |
viewer_file_class_init
function will be invoked after any
viewer_file_base_class_init
function. This will make sure the class structure of this new object is correctly initialized. Here,
viewer_file_class_init
is expected to override the object's class methods and setup the class' own methods. In the example above, the
constructed
method is the only overridden method: it is set to
viewer_file_constructed
.
g_object_new
has obtained a reference to an initialized class structure, it invokes its constructor method to create an instance of the new object, if the constructor has been overridden in
viewer_file_class_init
. Overridden constructors must chain up to their parent’s constructor. In order to find the parent class and chain up to the parent class constructor, we can use the
viewer_file_parent_class
pointer that has been set up for us by the
G_DEFINE_TYPE
macro.
g_object_constructor
is invoked by the last constructor in the chain. This function allocates the object's instance buffer through
g_type_create_instance
which means that the
instance_init
function is invoked at this point if one was registered. After
instance_init
returns, the object is fully initialized and should be ready to have its methods called by the user. When
g_type_create_instance
returns,
g_object_constructor
sets the construction properties (i.e. the properties which were given to
g_object_new
) and returns to the user's constructor.
g_object_new
and their order of invocation:
g_object_new
Invocation time | Function invoked | Function's parameters | Remark |
---|---|---|---|
First call to g_object_new for target type | target 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. | Never used in practice. Unlikely you will need it. |
target type's class_init function | On target type's class structure | Here, you should make sure to initialize or override class methods (that is, assign to each class' method its function pointer) and create the signals and the properties associated to your object. | |
interface's base_init function | On interface's vtable | ||
interface's interface_init function | On interface's vtable | ||
Each call to g_object_new for target type | target type's class constructor method: GObjectClass->constructor | On object's instance | If you need to handle construct properties in a custom way, or implement a singleton class, override the constructor method and make sure to chain up to the object's parent class before doing your own initialization. In doubt, do not override the constructor method. |
type's instance_init function | On the inheritance tree of classes from fundamental type to target type. the instance_init provided for each type is invoked once for each instance structure. | Provide an instance_init function to initialize your object before its construction properties are set. This is the preferred way to initialize a GObject instance. This function is equivalent to C++ constructors. | |
target type's class constructed method: GObjectClass->constructed | On object's instance | If you need to perform object initialization steps after all construct properties have been set. This is the final step in the object initialization process, and is only called if the constructor method returned a new object instance (rather than, for example, an existing singleton). |
Readers should feel concerned about one little twist in the order in which functions are invoked: while, technically, the class' constructor method is called before the GType's
instance_init
function (since
g_type_create_instance
which calls
instance_init
is called by
g_object_constructor
which is the top-level class constructor method and to which users are expected to chain to), the user's code which runs in a user-provided constructor will always run
after GType's
instance_init
function since the user-provided constructor
must (you've been warned) chain up
before doing anything useful.