7
votes

Fonctions virtuelles en C

Dupliqué possible:
Comment implémenter des fonctions virtuelles C ++ en C < / p>

en C ++, la seule différence entre une classe et une structure est le niveau d'accès par défaut. Vous pouvez donc avoir des fonctions virtuelles dans les structures, hériter des structures et ainsi de suite. Ma question est que pouvez-vous aussi faire cela en C?

c

7 commentaires

Voir Comment implémenter des fonctions virtuelles C ++ en C


Je sais comment ils sont implémentés en C ++, je me demandais simplement s'il travaillait dans C. Je ne savais pas que virtuel n'était pas un mot clé de C et toutes les recherches de Google m'ont conduit à C ++ Stuff ...


Ce n'est pas "la seule différence", ils diffèrent également dans leur héritage par défaut. C ne prend pas en charge les fonctions des membres d'aucun type - virtuel ou autre.


Pour mettre cela, votre question ne fait pas grand sens, c struct ne pas avoir de fonction membre. C n'a pas de pommes, il est donc inutile de demander s'il a des pommes vertes.


Eh bien, je ne savais pas que c structs n'a pas de fonctions ...


@Luchian: Bienvenue à cela. Ne soyez pas consterné si cette question est fermée car elle était déjà demandée précédemment (au moins deux fois). Voir la question liée qui a fourni Pierre.


J'aime le fait que la question était fermée comme une duplicata d'une question proche en tant que duplicata d'une question fermée comme un duplicata (chemin le plus court, un autre donne une indirection supplémentaire). Il devrait y avoir un badge pour cela.


5 Réponses :


5
votes

Non, vous ne pouvez pas. "Virtuel" ne fait pas partie du vocabulaire C, ni le "niveau d'accès" n'est "ni p>


10 commentaires

En effet, le mot clé virtuel ne fait pas partie du langage C. Cela ne signifie pas que la programmation orientée objet n'est pas possible dans C.


Je suis d'accord avec toi André, mais c'est à côté du point. L'OP a demandé spécifiquement des fonctions virtuelles à l'intérieur des structures, dans C.


À ce sujet, il n'y a pas de fonctions membres en C, sans que seuls les virtuels. Les pointeurs de fonction que les membres de données peuvent rendre la syntaxe d'un appel comme un peu comme une fonction de fonction de membre C ++, bien sûr.


-1: L'absence d'un mot virtuel Word réservé n'implique pas que vous ne pouvez pas avoir de fonctions de membre virtuel. Par cette définition, SmallTalk n'a pas non plus de polymorphisme.


Vous ne pouvez pas avoir des fonctions membres en C, virtuel ou non. point final. Le pointeur sur les fonctions est, le pointeur sur les fonctions pas fonctions membres. Sauve-moi la pédannie s'il vous plaît.


@HEXA: Le point est: déclarant le manque du mot-clé virtuel pour être la raison pour le manque de fonctions membres et al. n'est pas valide. La grammaire d'une langue n'a pas besoin de définir virtuel en tant que mot-clé pour définir le polymorphisme d'exécution-polymorphisme ou membre. De même, l'absence de telle production ou atome dans la grammaire ne déclare pas en elle-même l'absence de telles fonctions et comportements. Donc pas une réponse. Donc -1. point final.


@phresnel je n'ai même jamais dit mot clé. J'ai dit vocabulaire, ce qui signifie que le concept n'est pas la langue lexicale. Je pensais que c'était clair lorsque j'ai également illustré le «niveau d'accès», qui n'est pas un mot clé de C ++, ni sa partie de son vocabulaire, ses concepts.


@HEXA: Ensuite, j'ai mal compris (bien sûr que je ne connais pas votre connaissance de C ++), pensai-je par "vocabulaire", vous vouliez dire la définition de la grammaire / linguistique (oui, il y a parfois une corrélation entre les grammaires parlées et les grammaires artificielles). Mais je pense toujours que la question de l'OPS est suffisamment vague que la nommée alternatives est presque obligatoire; Mais ne pas faire, ce n'est pas une raison pour moi de -1, donc -1 * 0. Edit: Je supprimerais mon bowvote, mais je ne peux plus, à moins que votre message soit édité :(


C'est tout bon homme, ne vous inquiétez pas :)


J'ai coupé un excès d'espaces et je pourrais retirer mon bowvote, j'ai battu le système :)



12
votes

Vous pouvez faire des "fonctions virtuelles" avec des pointeurs de fonction stockés dans vos structures. Pour hériter, vous pouvez intégrer une structure dans une autre structure, mais la syntaxe, encore une fois, sera différente de ce que vous attendez. Vous pouvez écrire des programmes orientés objet dans C (Exemple classique est le fichier Unix / ... API), mais avec une syntaxe assez maladroite.

Réponses pertinentes ici: https://stackoverflow.com/search?q=c+virtual+fonctions


3 commentaires

En effet - le noyau Linux le fait beaucoup. A struct contenant plusieurs pointeurs de fonction (c'est-à-dire l'interface ). Chaque implémentation peut choisir de ne disposer que de certains des pointeurs de fonction attribués; Le reste est null.


Je savais que, je me demandais simplement si vous pouvez avoir virtuel dans C.


@Luchian - Le virtuel Le mot-clé et la restriction du compilateur associé n'existe pas dans C, car les autres ont dit. Mais vous pouvez obtenir un comportement similaire en C comme décrit par Yi_H et moi-même.



7
votes

c n'a pas de syntaxe natale pour les méthodes virtuelles. Cependant, vous pouvez toujours mettre en œuvre des méthodes virtuelles en mimiquant la manière dont C ++ implémente les méthodes virtuelles. C ++ stocke un pointeur supplémentaire à la définition de la fonction dans chaque classe pour chaque méthode virtuelle. Ainsi, vous pouvez simplement ajouter un pointeur de fonction à une structure pour simuler des méthodes virtuelles.

par exemple xxx


3 commentaires

+1 bonne tentative. Mais vous ne pouvez pas faire int (* f) (int x) = null; dans la définition de la structure elle-même.


Je suis d'accord avec Nawaz - cela doit être dans la définition de l'instance (ou comptez sur le compilateur pour laisser un champ non initialisé 0). De plus, vous devrez vous assurer que s.f n'est pas null avant de l'appeler.


@Eli et Nawaz: Merci d'avoir souligné cela. J'ai mis à jour le code et il compile maintenant avec GCC.



3
votes

Vous ne pouvez pas. C structs ne peut avoir de comportements. Ils ne peuvent avoir que des données.

S'il vous plaît voir http://www.topoder.com/tc?module= Statique & D1 = Tutoriels & D2 = Tenbestquesttions Pour les différences entre les structures C et C ++. Il est écrit dans la deuxième question.

Les structures C ++ sont aussi différentes que les classes C ++ sont différentes des structures C. C'est juste une analogie.

Plus, il n'y a pas d'héritage dans C. Sans hérité, que feriez-vous avec des fonctions virtuelles?


3 commentaires

Question: est une fonction de pointeur de fonction ou "comportement"?


Je ne sais pas beaucoup sur les pointeurs de la fonction, mais je pense que c'est une donnée. Après tout, un pointeur n'est-ce pas?


Vous pouvez trier des héritage en C en faisant la "base" struct le premier membre de la structure "enfant". Ensuite, après instancier de la structure "enfant", définissez simplement son pointeur de fonction sur la méthode remplacée.



5
votes

Vous pouvez simuler des fonctions virtuelles avec des pointeurs de fonction. Par exemple, xxx pré>

puis, vous pouvez "sous-classes" la structure avec quelque chose comme: p> xxx pré>

tout cela est plus intensif de main-d'œuvre et Erreur sujette, mais cela peut être fait. Ce type d'implémentation "héritage" et "remplacement" est une pratique courante dans certaines bibliothèques C bien connues, notamment jpeglib code> et libpng code>. Ils utilisent cette technique pour vous permettre de remplacer les procédures d'E / S si vous n'êtes pas satisfait de la norme CI / O. P>

EDIT STRY>: Comme indiqué dans les commentaires, une partie de Ce code repose sur un comportement non standard (officiellement) qui "arrive" à travailler sur la plupart des compilateurs. Le problème principal est que le code suppose que & m.base == & m code> (par exemple le décalage de l'élément code> code> est 0). Si ce n'est pas le cas, alors le casting dans Custom_Bar () code> entraîne un comportement non défini. Pour contourner ce problème, vous pouvez ajouter un pointeur supplémentaire dans struct foo code> comme tel: p> xxx pré>

puis, modifiez les choses qui touchent la distribution, P>

void setup_meh ( struct meh * m )
{
    m->base.hook = m;
   /* set up function pointers as usual... */
}

void custom_bar ( struct foo * f, int a, int b )
{
    struct meh * m = (struct meh*)f->hook;
    /* override. */
}


4 commentaires

Même si cela fonctionne, vous comptez sur des extensions de compilateur pour le type punning pouvant conduire à un comportement indéfini Blablabla. Cela fonctionne dans GCC et MSVC pour un fait. Également void (* bar) (int, int); doit être vide (* bar) (void *, int, int);


Merci, en effet le pointeur de la fonction a été déclaré faux. En effet, le matériel d'alignement repose sur des extensions du compilateur. Vous pouvez le rendre portable à l'aide d'un point de signature Extra Void * dans struct foo qui pointe sur "l'objet dérivé". Cependant, la technique est suffisamment populaire dans des bibliothèques bien connues pour être considérées comme "portable". Tout compilateur qui a fait ce type de caisse de code aurait beaucoup de plaintes de ses clients.


@HEXA: supprimé le comportement non défini. Voir la modification.


Bon travail, j'avais à nouveau upvote si je pouvais;)