Формирование цепочки

Формирование цепочки часто неточно определяется следующим набором условий:

Эту идиому можно использовать по разному:

Я лично не уверен что два последних способа использования являются хорошей идеей, н так как эта идиома программирования часто используется, этот раздел попытается объяснить как это реализуется.

Для явного формирования цепочки в реализации виртуального метода в родительском классе, вам сначала нужно обработать оригинальную структуру родительского класса. Этот указатель можно зтем использовать для доступа к оригинальному указателю функции класса и вызывать её непосредственно. [13]

Функция g_type_class_peek_parent используется для доступа к оригинальной родительской классовой структуре. Её ввод - это указатель на класс производного объекта и она возвращает указатель на оригинальную родительскую структуру класса. Код ниже показывает как вы должны её использовать:

static void b_method_to_call (B *obj, int a) { BClass *klass; AClass *parent_class; klass = B_GET_CLASS (obj); parent_class = g_type_class_peek_parent (klass); /* do stuff before chain up */ parent_class->method_to_call (obj, a); /* do stuff after chain up */ }

Многие люди использующие эту идиому в GTK+ хранят указатель на родительскую классовую структуру в глобальной статической переменной, чтобы избегать расточительных вызовов g_type_class_peek_parent для каждого вызова функции. Обычно, class_init callback-функция инициализирует глобальную статичную переменную. Это делает gtk/gtkhscale.c.



[13] Оригинальное прилагательное используемое в этом предложении весьма вредное. Для полного понимания что это значит, вы должны повторить как сструктуры класса инициализируются: для каждого объектного типа, классовая структура привязанная к объекту создаётся с помощью начального копирования классовой сструктуры родительского типа (просто memcpy) а зтем вызывается class_init callback-функция в результирующей структуре. Так как class_init callback-функция отвечает за перезапись классовой сструктуры с пользовательской перереализацией методов класса, мы не можем просто использовать изменённую копию родительской сструктуры класса сохранённую в нашем производном экземпляре. Мы хотим получить копию классовой сструктуры экземпляра родительского класса.