GObject 和继承
GObject and inheritance
我在 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;
}
但是当你有这种安排的时候。 child class 这样做: object_class->constructed = viewer_file_constructed;在 B 重写实际上是构造的唯一内存地址。所以表示G_OBJECT_CLASS(viewer_file_parent_class)->constructed(obj);将递归调用 B->constructed 。这不是我们想要的。
可能我没看懂,但我猜想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 classing 共享。并且所有地址在同一个 i...
- G_OBJECT_CLASS (B)->构造
- G_OBJECT_CLASS (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
};
如果两个类都定义了索引为 1 的 属性。那里会有问题,因为 glib 不知道应该由谁来处理。我想 child class B 会处理它但不正确,因为 B 可能正在等待,比如 PROP_DIRECTORY,但因为索引是相同的。 glib 能够发送到正确的实例吗?
我只能说,如果在寄存器上 glib 会根据层次结构级别添加一些偏移量,它就会起作用。有人可以解释这是如何工作的吗?我找不到任何包含所需技术细节的文档。
The internal representation should be something like:
不完全是。 GObject
和 GObjectClass
结构之间存在差异。每个对象实例有一个 GObject
结构实例,但整个 class.
只有一个 GObjectClass
实例
如果您有一个从 GObject
派生的 class FooBar
,FooBarClass
结构将类似于:
typedef struct
{
GObjectClass parent_class;
/* Virtual methods for FooBar instances: */
void (*vfunc) (FooBar *self);
} FooBarClass;
堆上会有一个FooBarClass
的实例。由于它包含整个 GObjectClass
结构作为其 parent_class
成员,这意味着它有自己的 finalize
、dispose
、get_property
等虚拟方法指针。
单独在堆中,有一个 GObjectClass
的 GObject 类型的实例。它包含另一组finalize
、dispose
等虚方法指针。
由于 FooBar
派生自 GObject
,foo_bar_parent_class
将被设置为指向 GObjectClass
实例。这就是允许链接的原因。
因此,如果你想实现 constructed
虚方法并向上链接(你 必须 向上链接 constructed
),只需按照 example code in the documentation you linked to does。没错。
The same applies with the properties. Because A defines it's
properties by an enum, that can go from 0 to N.
不正确。当使用 g_object_class_install_properties()
向 class 注册 属性 时,属性 索引与 class 结构内的 GObjectClass
实例相关联class。它们与 GObject 类型的独立 GObjectClass
结构无关。这个和上面的原理是一样的。
换句话说,没有 属性 索引的全局注册:它们都是按 class 完成的。因此,您可以(并且应该)为每个 classes 从 1 开始对属性进行索引。他们不会冲突。
请注意,如 g_object_class_install_properties()
的文档中所述,属性 索引 0 是特殊的,不得使用。您必须从 1 开始 属性 索引。
正如 ptomato 所说,这远远超出了文档的详细程度。你应该阅读源代码。
我在 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;
}
但是当你有这种安排的时候。 child class 这样做: object_class->constructed = viewer_file_constructed;在 B 重写实际上是构造的唯一内存地址。所以表示G_OBJECT_CLASS(viewer_file_parent_class)->constructed(obj);将递归调用 B->constructed 。这不是我们想要的。
可能我没看懂,但我猜想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 classing 共享。并且所有地址在同一个 i...
- G_OBJECT_CLASS (B)->构造
- G_OBJECT_CLASS (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
};
如果两个类都定义了索引为 1 的 属性。那里会有问题,因为 glib 不知道应该由谁来处理。我想 child class B 会处理它但不正确,因为 B 可能正在等待,比如 PROP_DIRECTORY,但因为索引是相同的。 glib 能够发送到正确的实例吗?
我只能说,如果在寄存器上 glib 会根据层次结构级别添加一些偏移量,它就会起作用。有人可以解释这是如何工作的吗?我找不到任何包含所需技术细节的文档。
The internal representation should be something like:
不完全是。 GObject
和 GObjectClass
结构之间存在差异。每个对象实例有一个 GObject
结构实例,但整个 class.
GObjectClass
实例
如果您有一个从 GObject
派生的 class FooBar
,FooBarClass
结构将类似于:
typedef struct
{
GObjectClass parent_class;
/* Virtual methods for FooBar instances: */
void (*vfunc) (FooBar *self);
} FooBarClass;
堆上会有一个FooBarClass
的实例。由于它包含整个 GObjectClass
结构作为其 parent_class
成员,这意味着它有自己的 finalize
、dispose
、get_property
等虚拟方法指针。
单独在堆中,有一个 GObjectClass
的 GObject 类型的实例。它包含另一组finalize
、dispose
等虚方法指针。
由于 FooBar
派生自 GObject
,foo_bar_parent_class
将被设置为指向 GObjectClass
实例。这就是允许链接的原因。
因此,如果你想实现 constructed
虚方法并向上链接(你 必须 向上链接 constructed
),只需按照 example code in the documentation you linked to does。没错。
The same applies with the properties. Because A defines it's properties by an enum, that can go from 0 to N.
不正确。当使用 g_object_class_install_properties()
向 class 注册 属性 时,属性 索引与 class 结构内的 GObjectClass
实例相关联class。它们与 GObject 类型的独立 GObjectClass
结构无关。这个和上面的原理是一样的。
换句话说,没有 属性 索引的全局注册:它们都是按 class 完成的。因此,您可以(并且应该)为每个 classes 从 1 开始对属性进行索引。他们不会冲突。
请注意,如 g_object_class_install_properties()
的文档中所述,属性 索引 0 是特殊的,不得使用。您必须从 1 开始 属性 索引。
正如 ptomato 所说,这远远超出了文档的详细程度。你应该阅读源代码。