GObject父类定义在class结构中的函数,必须是thread safe的
GObject中一般我们会把需要给子类继承的函数放在class结构里面,以供继承类来重载。一般的逻辑是,继承类重载了之后,实现了自己的自定义逻辑,然后再调用父类的该函数的默认实现。这样就会引起一个问题:多个子类可能会同时调用父类的某个函数默认实现。这样就会要求父类的这些函数实现必须是thread safe的。
之所以不把这些函数指针放在父类的instance结构中,就是因为放在instance结构中的话,子类重载了之后,就没法再调用父类的默认实现了,这样会导致代码冗余,难以维护。
为了验证上面的想法,写了一个程序。父类Dad,两个继承类son和daughter。通过测试程序可以看到,在父类开放的一个dad_print函数中,son和daughter都重载了这个函数,当son和daughter都调用父类dad_print的默认实现的时候,这两个函数指针的地址是一样的。所以,根据这个测试程序,结合GObject的文档,其实,GObject的内存结构和初始化逻辑应该是这样的:
1. g_object_new创建一个GObject。
2. 对于第一次g_object_new,从父类开始,一路往下,直到最终的子类,所以类的class结构都会被创建出来。对于继承类,他的class结构中,由于第一个member是父类的class结构,所以在内存中,继承类的class结构应该是父类的class结构,然后接下来是继承类自己的。
3. 每次g_object_new,instance结构都会被new一个新的。同样也是父类的instance结构开始往下,然后是子类的instance结构。由于一个类的instance可能有多个,所以这里是没有parent_instance这样的东西的,只有parent_class。
把上面的描述画成图应该是这样: