Gon*_*ado 0 inheritance gobject 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;
}
Run Code Online (Sandbox Code Playgroud)
但是,当你有这样的安排。子类执行此操作:object_class-> constructed = viewer_file_constructed; 实际上,在B覆盖中唯一构造的内存地址。因此,这意味着G_OBJECT_CLASS(viewer_file_parent_class)-> constructed(obj); 将调用B->递归构成。这不是我们想要的。
也许我听不懂,但我想B中的内存结构是这样的:
struct _B
{
A parent_instance;
/* instance members */
};
Run Code Online (Sandbox Code Playgroud)
内部表示应类似于:
[ Gobject struct memory ]
[ ]
[ Gobject variables ]
[ A struct memory ]
[ A variables ]
[ ]
[ B struct memory ]
[ B variables ]
Run Code Online (Sandbox Code Playgroud)
因此,在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
};
Run Code Online (Sandbox Code Playgroud)
如果两个分类都定义了索引为1的属性,那将会出现问题,因为glib不知道应该由谁处理。我想子类B会处理它,但处理不当,因为PROB_DIRECTORY可能说B正在等待,但是由于索引是相同的。glib能够发送到正确的实例吗?
我只能说如果在寄存器上glib会根据层次结构级别添加一些偏移量,那么它将起作用。有人可以解释这是如何工作的吗?我找不到任何具有所需技术细节的文档。
内部表示应类似于:
不完全的。GObject和GObjectClass结构之间存在差异。GObject每个对象实例只有一个结构实例,但GObjectClass整个类只有一个实例。
如果您有一个FooBar源自的类GObject,则该FooBarClass结构将类似于:
typedef struct
{
GObjectClass parent_class;
/* Virtual methods for FooBar instances: */
void (*vfunc) (FooBar *self);
} FooBarClass;
Run Code Online (Sandbox Code Playgroud)
FooBarClass堆上会有一个实例。因为它包含了整个GObjectClass结构作为其parent_class成员,这意味着它有自己的finalize,dispose,get_property等虚拟方法的指针。
在堆中单独存在一个GObjectClassGObject类型的实例。它包含另一组finalize,dispose等虚拟方法的指针。
由于FooBar源自GObject,foo_bar_parent_class将被设置为指向GObjectClass实例。这就是允许链接的原因。
因此,如果您想实现constructed虚拟方法并进行链接(必须链接constructed),请按照链接到的文档中的示例代码 do的方式进行操作。它是正确的。
这些属性同样适用。由于A通过枚举定义其属性,因此可以从0到N。
不正确 使用将属性注册到类时g_object_class_install_properties(),属性索引将与GObjectClass该类的类结构内的实例相关联。它们不与GObjectClassGObject类型的标准结构关联。这是与上述相同的原理。
换句话说,没有全局的属性索引注册表:所有这些都是按类完成的。因此,您可以(并且应该)为每个类从1开始属性索引。他们不会冲突。
请注意,如文档中g_object_class_install_properties()所述,属性索引0是特殊的,不得使用。您必须从1开始属性索引。
正如ptomato所说,这超出了适合文档的详细程度。您应该阅读源代码。