2016-04-22 2 views
0

J'ai les classes GLib Foo et DerivedFoo.Comment gérer le type de pointeur incompatible lors de l'affectation de méthodes virtuelles dans une classe dérivée?

La classe Foo a une méthode bar():

typedef struct _FooClass 
{ 
    GObjectClass parent_class; 

    void (*bar) (Foo *self); 
} FooClass; 

La classe DerivedFoo dérive de Foo et met en œuvre la méthode bar():

void derived_foo_bar (DerivedFoo *self); 

static void 
derived_foo_class_init (DerivedFooClass *klass) 
{ 
    FooClass *foo_class = FOO_CLASS (klass); 
    // Compiler warning appears here 
    foo_class->bar = derived_foo_bar; 
} 

Le message d'avertissement est:

warning: assignment from incompatible pointer type 

Les pointeurs ne sont pas compatibles, car le type du paramètre self est différent (Foo * par rapport à DerivedFoo *).

Est-ce la bonne façon d'implémenter des méthodes virtuelles dans GObject?

Si oui, peut/devrais-je faire quelque chose à propos de l'avertissement du compilateur?

+1

Comment 'DerivedFoo' dérive-t-il de' Foo'? Il n'y a pas d'héritage dans C. – atturri

+0

Cette question est un bon moyen de lancer un argument sur la [règle d'alias strict] (https://stackoverflow.com/questions/98650/what-is-the-strict-aliasing-rule) . – user3386109

+0

Vous pouvez le transformer en 'foo_class-> bar = (void (*) (Foo *)) derived_foo_bar;'. Je suppose que l'utilisation judicieuse de 'typedef' et/ou de macros le rendrait moins moche! –

Répondre

3

Vous quittez le prototype de fonction pour respecter la classe de base virtuelle et le transposez dans votre fonction à l'aide de macros/fonctions glib.

void derived_foo_bar (Foo *self); 

static void 
derived_foo_class_init (DerivedFooClass *klass) 
{ 
    FooClass *foo_class = FOO_CLASS (klass); 
    // Compiler warning appears here 
    foo_class->bar = derived_foo_bar; 
} 

void derived_foo_bar (Foo *_self) 
{ 
    DerivedFoo *self = DERIVED_FOO (self); /* or whatever you have named this macro, using the standard GLIB semantics */ 
/* If self is not compatible with DerivedFoo, a warning will be issued from glib typecasting logic */ 
}