Re: [gtk-list] [Q] base_class_init_func.

On 20 Jan 1999, Thomas Mailund Jensen wrote:

> I guess I could track this down myself, but it's always easier to ask
> someone who knows ;)
> What is the idea behind the base_class_init_func entry in GtkTypeInfo?
> Is there a reason [1] to have two class init functions?  In which
> order are they called, and how do they behave in relation to
> inheritance?

hm, the answer to this question actually requires some basic knowledge
on how the gtk type system allocates new widgets and classes in general,
i'll try to outline the basic functionality along the example creation of
a list widget right after gtk_init(), i.e.

gtk_init (&argc, &argv);
list = gtk_list_new ();

gtk_init() will cause gtk_type_init() to be called which does some very basic
type system setup, that is
- a hash table is setup for the type names
- built in types are registered, e.g. those from the GtkFundamentalType enum
  (amongst them is GTK_TYPE_OBJECT) and all enumeration types.

registering a type means adding its name to the type hash table, allocating
space to store some additional type informations, e.g. those from GtkTypeInfo
and assigning a type id.

gtk_list_new() will then cause a new widget plus its class(es) to be allocated
and initialized. this works as follows,

- it registers the GtkList type by calling gtk_list_get_type() and retrive
  the list's type id.
- gtk_type_new() will then check for the GtkList type's class to be
  initialized, if that is not the case the class will be initialized.
- the list widget itself is allocated and then initialized with the
  object initialization functions of all parent types.

the class initialization, basically works like this (recursively)
- retrive the type's parent class if the type has a parent, if the parent's
  class isn't yet initialized do that.
- allocate space for the new class and then copy the parent classes contents
  into the newly allocated space.
- invoke the base_class_init functions of all parent types for the newly
  allocated class.
- invoke the class_init function of the current type for the newly allocated

thus for a GtkList class which inherits like this:
 GtkObject             (provides base_class_init, class_init and object_init)
   +GtkWidget                           (provides class_init and widget_init)
      +GtkContainer (provides base_class_init, class_init and container_init)
         +GtkList                    (provides class_init and container_init)

first the classes for GtkObject, GtkWidget and GtkContainer are created and
then the list class itself:

g_new0 (object_class)
gtk_object_base_class_init (object_class)
gtk_object_class_init (object_class)

g_new0 (widget_class)
memcpy (widget_class, object_class)
gtk_object_base_class_init (widget_class)
gtk_widget_class_init (object_class)

g_new0 (container_class)
memcpy (container_class, widget_class)
gtk_object_base_class_init (container_class)
gtk_container_base_class_init (container_class)
gtk_container_class_init (container_class)

g_new0 (list_class)
memcpy (list_class, container_class)
gtk_object_base_class_init (list_class)
gtk_container_base_class_init (list_class)
gtk_list_class_init (list_class)

the actuall widget allocation is then

g_new0 (list)
gtk_object_init (list)
gtk_widget_init (list)
gtk_container_init (list)
gtk_list_init (list)

thus, class_init functions will only be called once upon creation of the
associated class. base_class_init functions will be called upon creation
of the associated class *and* upon creation of all derived classes.
the reason things are setup this way is that usually derived classes only
contain additional stuff compared to their parent class and thus a simple
memcpy will do for the creation.
this assumption doesn't hold for all cases, e.g. a classes signal array
pointers need to be reset upon class creation (since child classes
may introduce new signals, and that requires modifications to the
signal arrays) and some certain other values as well, e.g. the set_arg
and get_arg functions because, those don't chain in the usuall manner and
will get called per-class-instance only.

i hope i was able to clarify things a bit.

> 	/mailund


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]