我在Glib上做了一些严肃的软件。我意识到有一些我不太了解的主题。 IRC也没有帮助......
当我们进行继承时,我们可以有两个分支。第一个A直接从GObject继承,B继承自A.然后我来到了这个:
https://developer.gnome.org/gobject/stable/chapter-gobject.html
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;
}
但是当你有这种安排时。子类执行此操作:object_class-> construct = viewer_file_constructed;在B中实际上覆盖了构造的唯一内存地址。所以它意味着G_OBJECT_CLASS(viewer_file_parent_class) - > construct(obj);将以递归方式调用B->。而这不是我们想要的。
也许我不明白,但我认为B中的内存结构是这样的:
struct _B
{
A parent_instance;
/* instance members */
};
内部表示应该是这样的:
[ Gobject struct memory ]
[ ]
[ Gobject variables ]
[ A struct memory ]
[ A variables ]
[ ]
[ B struct memory ]
[ B variables ]
因此,在B中投射时的GObject内存是由B和A分类共享的。并且所有地址都是相同的...
这是对的吗? 所以,如果我想覆盖构造...我是否必须保存之前的指针,然后在我的init中覆盖它?我处理完毕后可以打电话给原来的那个吗?
这同样适用于属性。因为A通过枚举定义它的属性,可以从0到N。
所以我认为B属性应该从N开始,而不是0.否则A的属性由B处理,可能具有不同的数据结构和名称。
检查一下: https://developer.gnome.org/gobject/stable/gobject-properties.html
enum
{
PROP_FILENAME = 1,
PROP_ZOOM_LEVEL,
N_PROPERTIES
};
如果两个clases都定义了索引为1的属性。那里会出现问题,因为glib不知道应该处理谁。我想孩子B级会处理它但是不正确,因为可能B正在等待,比如PROP_DIRECTORY,但是因为索引是相同的。 glib能够发送到正确的实例吗?
如果在寄存器上glib将根据层次结构级别添加一些偏移量,我只能使用它。有人可以解释这是如何工作的吗?我找不到任何具有所需技术细节的文件。
答案 0 :(得分:6)
内部表示应该是这样的:
不完全。 GObject
和GObjectClass
结构之间存在差异。每个对象实例有一个GObject
结构实例,但整个类只有一个GObjectClass
实例。
如果您的某个类FooBar
派生自GObject
,那么FooBarClass
结构将类似于:
typedef struct
{
GObjectClass parent_class;
/* Virtual methods for FooBar instances: */
void (*vfunc) (FooBar *self);
} FooBarClass;
堆上会有FooBarClass
的实例。由于它包含整个GObjectClass
结构作为其parent_class
成员,这意味着它有自己的finalize
,dispose
,get_property
等虚拟方法指针。
在堆中,有一个GObject类型的GObjectClass
实例。它包含另一组finalize
,dispose
等虚拟方法指针。
由于FooBar
派生自GObject
,foo_bar_parent_class
将设置为指向GObjectClass
实例。这是允许链接的原因。
因此,如果您要实施constructed
虚拟方法并进行链接(必须链接constructed
),请执行example code in the documentation you linked to does。这是对的。
这同样适用于属性。因为A定义了它 枚举的属性,可以从0到N.
不正确的。使用g_object_class_install_properties()
向类注册属性时,属性索引与该类的类结构中的GObjectClass
实例相关联。它们与GObject类型的独立GObjectClass
结构无关。这与上述原理相同。
换句话说,没有属性指数的全球注册表:它都是按类进行的。因此,您可以(并且应该)为每个类启动1的属性索引。他们不会发生冲突。
请注意,如g_object_class_install_properties()
的文档中所述,属性索引0是特殊的,不得使用。您必须从1开始索引属性。
正如ptomato所说,这超出了适合文档的详细程度。你应该阅读源代码。