GLib
  • Initial page
  • I. Концепция
    • Background
    • Типы данных и программирование
  • Динамическая система типов Glib
    • Введение
    • Функции копирования
    • Соглашения
    • Неинстанциируемые не классифицированные базовые типы
    • Инстанциируемые классифицируемые типы: объекты
    • Неинстанциированные классифицированные типы: Интерфейсы.
  • Основной класс GObject
    • Введение
    • Инстанциация объекта
    • Объектное управление памятью
    • Свойства объекта
  • Система сообщений GObject
    • Замыкания
    • Сигналы
  • II. Описание API
    • GType
    • GTypePlugin
    • GTypeModule
    • GObject часть 1
    • GObject часть 2
    • Enums and Flags
    • GBoxed
    • Generic Values
    • Parameters and Values часть 1
    • Parameters and Values часть 2
    • Parameters and Values часть 3, ага
    • Value arrays
  • III. Описание инструментов
    • glib-mkenums
    • glib-genmarshal
    • gobject-query
  • IV. Руководство
    • Как определить и реализовать новый GObject?
    • Объектные методы
    • Как определять и реализовывать Интерфейсы?
    • Как создавать и использовать сигналы
    • Как пользователи могут злоупотреблять сигналами (и почему некоторые думают что это хорошо)
  • V. Об инструментах
    • Об инструментах
  • GTK 4
    • GtkApplication и GtkApplicationWindow
    • Widgets
Powered by GitBook
On this page

Was this helpful?

  1. Основной класс GObject

Инстанциация объекта

PreviousВведениеNextОбъектное управление памятью

Last updated 6 years ago

Was this helpful?

Семейство функций могут использоваться для инстанциации любого GType который наследует основной тип GObject. Все эти функции проверяют класс и экземпляр сструктуры на правильную инициализацию в системе типов glib и вызывают один за другим метод конструктора класса, который используется для:

  • Распределение и очистка памяти с помощью ,

  • Инициализацию экземпляра объекта с созданными свойствами.

Хотя можно устанавливать класс и члены объекта (кроме полей указывающих на родителей) в нули, некоторые считают хорошей практикой установку явных значений для них.

Объекты которые наследуют GObject позволяют переписывать этот метод создания класса: однако перед этим, они должны привязываться к их родительскому методу конструктора:

 GObject*   (*constructor)     (GType                  type,
                                 guint                  n_construct_properties,
                                 GObjectConstructParam *construct_properties);

Например ниже показано как MamanBar перезаписывает родительский конструктор:

#define MAMAN_TYPE_BAR                  (maman_bar_get_type ())
#define MAMAN_BAR(obj)                  (G_TYPE_CHECK_INSTANCE_CAST ((obj), MAMAN_TYPE_BAR, MamanBar))
#define MAMAN_BAR_CLASS(klass)          (G_TYPE_CHECK_CLASS_CAST ((klass), MAMAN_TYPE_BAR, MamanBarClass))
#define MAMAN_IS_BAR(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MAMAN_TYPE_BAR))
#define MAMAN_IS_BAR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MAMAN_TYPE_BAR))
#define MAMAN_BAR_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), MAMAN_TYPE_BAR, MamanBarClass))

typedef struct _MamanBar MamanBar;
typedef struct _MamanBarClass MamanBarClass;

struct _MamanBar {
  GObject parent;
  /* instance members */
};

struct _MamanBarClass {
  GObjectClass parent;

  /* class members */
};

/* used by MAMAN_TYPE_BAR */
GType maman_bar_get_type (void);

static GObject *
maman_bar_constructor (GType                  type,
                       guint                  n_construct_properties,
                       GObjectConstructParam *construct_properties)
{
  GObject *obj;

  {
    /* Invoke parent constructor. */
    MamanBarClass *klass;
    GObjectClass *parent_class;  
    klass = MAMAN_BAR_CLASS (g_type_class_peek (MAMAN_TYPE_BAR));
    parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass));
    obj = parent_class->constructor (type,
                                     n_construct_properties,
                                     construct_properties);
  }
  
  /* do stuff. */

  return obj;
}

static void
maman_bar_instance_init (GTypeInstance   *instance,
                         gpointer         g_class)
{
  MamanBar *self = (MamanBar *)instance;
  /* do stuff */
}

static void
maman_bar_class_init (gpointer g_class,
                      gpointer g_class_data)
{
  GObjectClass *gobject_class = G_OBJECT_CLASS (g_class);
  MamanBarClass *klass = MAMAN_BAR_CLASS (g_class);

  gobject_class->constructor = maman_bar_constructor;
}

GType maman_bar_get_type (void)
{
  static GType type = 0;
  if (type == 0) {
    static const GTypeInfo info = {
      sizeof (MamanBarClass),
      NULL,   /* base_init */
      NULL,   /* base_finalize */
      maman_bar_class_init,   /* class_init */
      NULL,   /* class_finalize */
      NULL,   /* class_data */
      sizeof (MamanBar),
      0,      /* n_preallocs */
      maman_bar_instance_init    /* instance_init */
    };
    type = g_type_register_static (G_TYPE_OBJECT,
                                   "MamanBarType",
                                   &info, 0);
  }
  return type;
}

Если пользователь инстанциирует объект MamanBar с помощью:

MamanBar *bar = g_object_new (MAMAN_TYPE_BAR, NULL);

Если это первая инстанциация такого объекта, функция maman_b_class_init будет вызвана после любой функции maman_b_base_class_init. Это позволит убедиться в том, что структура класса этого нового объекта правильно инициализирована. Здесь maman_bar_class_init как ожидается отменит объектные методы класса и установит собственные. В примере выше, метод конструктора единственный отменённый метод: он устанавливается в maman_bar_constructor.

Время вызова

Вызываемая функция

Параметры функции

Ремарка

функция base_init целевого типа

В дереве иерархии классов из базового типа в целевой тип. base_init вызывается один раз для каждой сструктуры класса.

У меня нет идей как это может использоваться. Если вы знаете хороший работающий пример как используется base_init класса, пожалуйста, сообщите мне.

Функция class_init целевого типа

В структуре класса целевого типа

Здесь вы должны убедиться что инициализировали или отменили методы класса (то есть, указатели функций связанные с каждым методом класса) и создать сигналы и свойства связанные с вашим объектом.

Интерфейсная функция base_init

В интерфейсной vtable

интерфейсная функция interface_init

В интерфейсной vtable

Метод конструктора класса целевого типа: GObjectClass->constructor

В экземпляре объекта

Если вам нужно завершить инициализацию объекта после того как все свойства конструкции установлены, отмените метод конструктора и проверьте цепочку объектного родительского класса перед выполнением вашей собственной инициализации. Если сомневаетесь, не переписывайте метод конструктора.

типовая функция instance_init

В дереве иерархии классов из базового типа в целевой тип. instance_init обеспечивается для каждого типа вызывая для каждого экземпляра сструктуры.

Обеспечьте функцию instance_init для инициализации вашего объекта перед установкой конструкционных свойств. Это предпочтительный способ инициализации экземпляра GObject. Эта функция эквивалентна конструкторам C++.

Как только получила ссылку на инициализированную структуру класса, она вызывает свой метод конструктора для создания экземпляра нового объекта. Затем она просто отменяет maman_bar_class_init в maman_bar_constructor, вызывая её позже, потому что была реализована правильно, она связывается со своим родительским конструктором. Проблема заключается в поиске родительского конструктора. Метод (используемый в исходном коде GTK+) состоит в том, чтобы сохранить оригинальный конструктор в статической переменной в maman_bar_class_init и зтем многократно использовать её из maman_bar_constructor. Это вполне возможно и очень просто, но это не очень хороший метод, предпочтительней использовать функции и .

Наконец, попорядку, g_object_constructor вызывается последней в цепочке. Эта функция распределяет инстанциированный объектный буфер через это значит в этой точке вызывается функция instance_init если она зарегистрирована. После выполнения instance_init, объект полностью инициализирован и должен быть готов ответить на любой пользовательский запрос. Когда выполнена, g_object_constructor устанавливает свойства конструкции (то есть: свойства полученные в ) и возвращается в пользовательский конструктор которому позволяет выполнить подходящую инициализацию экземпляра...

Процессс описанный выше может показаться немного сложным (он действительно усложнён по моему..) но он может быть резюмирован таблицей ниже, которая описывает и порядок её вызова.

Таблица 4.

Первый вызов для целевого типа

Каждый вызов для целевого типа

Читатели могут быть смущены некоторым обстоятельством в порядке вызова функций: в то время как, технически, метод классового конструктора вызывается перед GType функцией instance_init (так как которая вызывает instance_init вызывается g_object_constructor которая находится на верхнем уровне классового метода конструктора и к которому привязываются пользователи), пользовательский код который выполняется в обеспеченном пользователем конструкторе будет всегда выполняться после GType функции instance_init, так как конструктор обеспеченный пользователем должен (вы были предкпреждены) привязываться перед выполнением чего-либо полезного.

g_object_new
g_type_create_instance
g_object_new
g_type_class_peek
g_type_class_peek_parent
g_type_create_instance
g_type_create_instance
g_object_new
g_object_new
g_object_new
g_type_create_instance
g_object_new
g_object_new