基于前面知识,我们知道GObject是静态类对象,可以创建N个实例,但是只会创建一个类结构体对象。

比如常用 GObjectClass里面的:

alt text

  1. 类里面函数指针,可以做信号的默认处理函数(指向默认处理函数)

  2. 子类可以重写父类里面的函数指针(指向的处理函数),进而实现多态。

  3. 子类也可以调用父类的函数指针。

1 对象初始化过程分析

1.1 区分不同父类内存区域

需要主要两部分内存空间:一是父类自身占用的内存空间,另一个是子类复制父类部分的内存空间

比如 GtkWIdget

  1. GTK_WIDGET_GET_CLASS 得到的是自身拷贝父类部分的内存空间。(这部分有些数据已经被 gtk_widget_class_init函数修改)

  2. gtk_widget_parent_class 父类的内存部分。(不会被子类修改,两个类是独立的)

alt text

1.2 分析初始化过程

  1. 父类(类结构体)区域直接拷贝(不会调用父类class_init初始化函数),然后调用该对象的类初始化函数 class_init 。

  2. 实例(结构体),不是直接拷贝父类实例结构体区别,而且调用父类实例结构体初始化函数。

alt text

2 对象销毁过程分析

2.1 区分两种销毁函数

g_object_unref解引用到零的时候执行会先调用dispose,再finalize:

  1. G_OBJECT_GET_CLASS (object)->dispose (object);,这部分应该释放一些对其他对象的引用,释放信号连接等操作。可以参考GtkWidget

  2. G_OBJECT_GET_CLASS (object)->finalize (object);,这部分应该释放相关变量的内存。可以参考GtkWidget

alt text

通过比较查看 g_object_unref 函数发现,dispose中可以重新对对象进行引用,使得最终不会调用finalize函数。finalize只用被调用完成后,实例结构体的内存就会被释放。

2.2 链式释放分析

先执行完该对象的finalize,最后会执行父类的->finalize,依次链式执行。

alt text

3 对象属性注册与设置分析

3.1 每个类都会有相关的设置和得到属性函数

属性都是注册在 GobjectClass 里面,因为属性是 Gobject 对象具备的功能。虽然图中可以看到,每次继承,都会修改类中, GobjectClass(自己类拷贝的区域)的设定属性和得到属性部分。

alt text

3.2 如何对应到每个类,使用相应的设置属性函数

是否继承了父类的属性:

答:继承了父类的属性。那既然继承了父类的属性,设定属性和得到属性函数,每个类对应的函数都不一样,系统是如何区分的??

如何区别一个类中,属性是继承于那个对象:

alt text

alt text