Я делал серьезное программное обеспечение на 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->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 ]
Таким образом, память GObject при приведении в B является общей для классов B и A. И все адреса одинаковые на одном и том же я...
- 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
};
Если оба clases определяют свойство с индексом 1. Там будет проблема, потому что glib не знает, кто должен обрабатывать. Я предполагаю, что дочерний класс B справится с этим, но неправильно, потому что, возможно, B ожидает, скажем, PROP_DIRECTORY, но поскольку индекс тот же. Сможет ли glib отправить в нужный экземпляр?
Я могу только сказать, что это сработает, если в регистре glib будет добавлено некоторое смещение в зависимости от уровня иерархии. Может кто-нибудь объяснить, как это на самом деле работает? Я не могу найти ни одного документа с требуемыми техническими подробностями.