1

J'ai lu le livre Comprendre et utiliser les pointeurs C et essayer de compiler le code ci-dessous. Mais après la compilation, j'ai reçu l'avertissement: affectation à partir du type de pointeur incompatible.le pointeur de fonction et la fonction est incompatible à cause des arguments

J'ai vérifié le code et trouver le pointeur de fonction fptrSet et la fonction ShapeSetX est incompatible parce que le premier argument de fptrSet est void * et la fonction ShapeSetX est Shape *.

Comment puis-je résoudre ce problème? Merci!

typedef void (*fptrSet)(void*, int); 
typedef int (*fptrGet)(void*); 
typedef void (*fptrDisplay)();  

typedef struct _vfunc 
{ 
    fptrSet  setX; 
    fptrGet  getX; 
    fptrSet  setY; 
    fptrGet  getY; 
    fptrDisplay display;  
} vFunc;  

typedef struct _shape 
{ 
    vFunc function; 
    int x; 
    int y; 
} Shape; 

void displayShape(){ 
    printf("Shape\n"); 
} 
void ShapeSetX(Shape *shape, int x){ 
    shape->x = x; 
} 
void ShapeSetY(Shape *shape, int y){ 
    shape->y = y; 
} 
int ShapeGetX(Shape *shape){ 
    return shape->x; 
} 
int ShapeGetY(Shape *shape){ 
    return shape->y; 
}  

Shape *newShape() 
{ 
    Shape *shape = (Shape *)malloc(sizeof(Shape)); 
    shape->x = 10; 
    shape->y = 10; 
    shape->function.setX = ShapeSetX; 
    shape->function.getX = ShapeGetX; 
    shape->function.setY = ShapeSetY; 
    shape->function.getY = ShapeGetY; 
    shape->function.display = displayShape; 
    return shape; 
} 
+0

Je pense que vous pouvez également changer le 'typedef void (* fptrSet) (void *, int) 'à' typedef void (* fptrSet) (Shape *, int) 'et la même chose pour' fptrGet'. –

+0

@KevinWallis Je pense qu'il veut quelque chose comme la table virtuelle de C++, donc parce qu'il n'y a pas d'héritage en C, il doit utiliser 'void' pour autoriser la structure" dérivée "de' Shape' – Garf365

+0

@KevinWallis @ Garf365 a raison, comme vous voir ce code est essayer de simuler le vtable à partir de C++, donc l'argument doit être 'void *' – FatMouse

Répondre

1

Vous devez respecter la définition du pointeur: pointeur besoin que le premier paramètre est un pointeur d'annuler, de sorte que votre mise en œuvre de la fonction doit avoir le premier paramètre comme vide:

void ShapeSetX(void *void_shape, int x){ 
    Shape *shape = (Shape*) void_shape; 
    shape->x = x; 
} 
void ShapeSetY(void *void_shape, int y){ 
    Shape *shape = (Shape*) void_shape; 
    shape->y = y; 
} 
int ShapeGetX(void *void_shape){ 
    Shape *shape = (Shape*) void_shape; 
    return shape->x; 
} 
int ShapeGetY(void *void_shape){ 
    Shape *shape = (Shape*) void_shape; 
    return shape->y; 
} 
+0

Vos moulages sont incorrects, sortez-les –

+0

@MM désolé, corrigé – Garf365

+0

@ Garf365 Merci pour votre réponse et vous avez ce que je veux. J'essaie d'utiliser le code pour simuler le «ploymorphisme» de POO. Vraiment merci ! – FatMouse

1

J'allais dire « Pourquoi ne remplacez-vous pas void par Shape puis? ", jusqu'à ce que je me rende compte que Shape n'a pas encore été défini - vous ne pouvez pas non plus échanger les deux définitions, car Shape a besoin de vFunc qui a besoin de typedef s.

Alors, faites ceci:

typedef struct _shape Shape; // Define _shape and Shape later 

typedef void (*fptrSet)(Shape*, int); 
typedef int (*fptrGet)(Shape*); 
typedef void (*fptrDisplay)();  

Si votre compilateur ne pas comme ça, vous devrez peut-être changer pour:

typedef struct _shape; // Define _shape later 

typedef void (*fptrSet)(struct _shape*, int); 
typedef int (*fptrGet)(struct _shape*); 
typedef void (*fptrDisplay)();  
+0

Avec cette solution, vous pouvez utiliser '_vfunc' avec une autre structure que' Shape'. Je pense que OP veut une solution pour avoir une solution "d'héritage" dans C – Garf365

+0

Par exemple avec une fonction 'int getXOfInstance (instance void *, vFunc * vfunc) {return vfund-> getX (instance);}' – Garf365

+0

@Garf je pensais à cela - mais avec des noms comme 'set/get '' X/y' et' Display' tout sonnait plutôt "Shape-y" –