Re: GObject constructors



On Thu, Nov 10, 2005 at 08:21:46PM +0100, David Necas (Yeti) wrote:
> On Wed, Nov 09, 2005 at 06:43:17PM +0100, Jacob Kroon wrote:
> > I'm having problems with figuring out how to initialize my data properly.
> > My scenario is that I have:
> > 
> > struct Parent {
> >    GObject parent;
> >    float *data;
> > }
> > 
> > struct ParentClass {
> >    GObjectClass parent;
> >    int data_size;
> > }
> > 
> > struct Child {
> >    Parent parent;
> > }
> > 
> > struct ChildClass {
> >    ParentClass parent;
> > }
> > 
> > Each subclass of Parent will use different, but fixed data sizes, so I 
> > want Child to tell Parent how much
> > data it needs, and then let Parent initialize the data accordingly.
> > 
> > The way I thought would work was this:
> > 
> > 1. In child_class_init(*klass):
> >    PARENT_CLASS(klass)->data_size = specific_size_for_this_subclass;
> > 2. In parent_instance_init(*obj)
> >    klass = PARENT_GET_CLASS(obj);
> >    obj->data = g_new(float, klass->data_size);
> > 
> > but this wont work since PARENT_GET_CLASS(obj) in parent_instance_init() 
> > returns the class for Parent,
> > not the subclass ChildClass, so data_size won't have the value I intended.
> 
> I had similar problem and came to conclusion it's impossible
> to implement it this way, or at least it's against inheritance.
> 
> However, you can keep 1. as it is and define a parent_instance_setup()
> method that contains the common code and call that from
> child constructor:
> 
> 2a. parent_instance_setup(obj) {
>         klass = PARENT_GET_CLASS(obj)
>         obj->data = g_new(float, klass->data_size);
>     }
> 
> 2b. child_instance_init(obj) {
>         parent_instance_setup(obj);
>     }


actually, you can take advantage of the fact that
real prototype of GInstanceInitFunc is

typedef void   (*GInstanceInitFunc)          (GTypeInstance   *instance,
                                              gpointer         g_class);

so, instead of using G_DEFINE_TYPE do it manually and use the
fuller prototype:

static void
parent_init (Parent *parent, ParentClass *real_class)
{
  /* Real class will point to the concrete class instance,
     ie the child's class. */
  parent->data = g_new (float, real_class->size);
}

GType parent_get_type()
{
  static GType io_type = 0;
  if (!io_type)
    {
      static const GTypeInfo io_info =
      {
        sizeof(ParentClass),
        (GBaseInitFunc) NULL,
        (GBaseFinalizeFunc) NULL,
        (GClassInitFunc) gsk_io_class_init,
        NULL,           /* class_finalize */
        NULL,           /* class_data */
        sizeof (Parent),
        0,              /* n_preallocs */
        (GInstanceInitFunc) gsk_io_init,
        NULL            /* value_table */
      };
      io_type = g_type_register_static (G_TYPE_OBJECT, "Parent",
                                        &io_info, G_TYPE_FLAG_ABSTRACT);
    }
  return io_type;
}

etc



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