Les membres privés dans les structures C

18 mai 2008 · Posted in C / C + +

Cette semaine, ici au travail avait une preuve de plus que le paradigme de programmation est quelque chose de complètement indépendant du langage, c'est à dire qu'il n'est pas parce que vous êtes la programmation en C + +, compilé avec g + + que votre code sera orientée objet si peu, si vous programmez dans votre code C ANSI doit être structurée ou vous serez disqualifié de la programmation orientée objet.

Je lis à droite, l'orientation objet en C ANSI?

Oui et non!

Des choses comme héritage, le polymorphisme et la surcharge sont compliqués à faire / émuler en C, mais vous pouvez programmer en utilisant un style qui se comportaient de la même à l'orientation objet. Le libdfb est écrit en C, mais «orientée objet», de sorte que vous créer, manipuler il détruit les éléments qui se comportent comme des objets.

Ici au travail, nous avons un système d'abstraction matérielle en C qui se connecte avec une interface graphique en C + +. La couche la plus basse, a aussi été écrit en C (et très bien écrit, disent d'ailleurs) avec ces techniques, en simulant une orientation objet. Une telle technique, a attiré mon attention en portant une de ces notes de livres C.

Lors de la compilation de code C, chaque symbole n'est visible que dans l'unité de compilation dans laquelle elle a été déclarée, sauf s'il est de nouveau déclaré que extern dans d'autres unités. Ainsi, vous pouvez "cacher" certains symboles au sein de son unité de compilation, les rendant inaccessibles au monde extérieur. Nous avons avec ce paquet.

L'unité de compilation est l'ensemble des fichiers qui, après pré-traitées et de générer un code compilé seul objet. Fondamentalement (mais pas exactement), nous pouvons prendre pour chaque fichier de mise en œuvre de compilation du code source de l'unité (*. c, *. cpp. Etc.) Plus de détails sur les étapes de la compilation C et C + + peut être trouvé sur le blog de ​​Caloni .

En utilisant cette information, nous pouvons créer une structure en C ANSI dans lequel ses membres internes sont «privés». La magie est dans la définition des états piège au sein de l'unité de compilation et de créer des méthodes d'accès pour ces membres. Pour cela nous utilisons les notes qui nous montrent la différence entre la déclaration et la définition des éléments dans C:

Déclaration ou manifeste: le compilateur présente un identifiant sans dire beaucoup plus sur sa signification, à savoir, indique au compilateur que l'identifiant XXX existe, mais on sait peu sur ce qu'elle représente.
Ex

  a ; extern int a;
 void ) ; nulle bla (void);
 struct st_data; 

Définition et mise en œuvre: indique au compilateur que l'identificateur est donné, telles que la quantité de mémoire devraient être alloués à elle et quelle est l'adresse de mémoire où l'on peut trouver, entre autres choses.
Ex

  int a;
 void ) { /* Do anything. nulle bla (void) {/ * Ne rien.  * /}
 /* Some members. st_data struct {/ * Ajouter des membres.  * /} 

Lorsque nous parlons de structures et de types, sans définir le compilateur ne peut pas allouer de la mémoire pour eux, car rien n'est connu au sujet de combien d'espace vous avez besoin d'une variable de ce type. D'autre part, parfois, sans une plainte, le linker ne peut pas savoir ce que ce symbole existe.

Lorsque nous déclarons une structure dans un en-tête, généralement, nous avons également mis leurs membres là-bas et tout ce temps, nous ajoutons un en-tête de notre source, nous avons inclus dans l'unité de compilation que les deux la déclaration de source que la définition de cette structure, ce qui rend les membres du public estutura à cette unité de compilation. Cela nous permet d'accéder directement à ses membres.

Si nous déclaration distincte du symbole seule définition qui représente la structure est disponible, mais pas ses membres. Ainsi, toute tentative d'accès direct à un membre, va générer une erreur de compilation. Un effet secondaire intéressant est que le compilateur ne sait rien au sujet de la taille de la structure, vous ne pouvez pas définir directement une variable de type structure, seul un pointeur vers elle, parce que tous les pointeurs ont la même taille et le compilateur a besoin que le nom du symbole le type de pointeur pour créer.

Nous avons ensuite mytype.h tête comme ceci:

 # Ifndef # define MY_TYPE_H MY_TYPE_H / * Le typedef n'est pas simplement de répéter la struct mot.  _mytype * / / * La déclaration n'est que le passage: * / / * _MYTYPE struct * / typedef struct _MYTYPE 

La mise en œuvre mytype.c:

  # Include "mytype.h"

 Fopen
 # Inclure
 # Include <string.h>

 /* Aqui fica a definição da estrtura. _MYTYPE Struct {/ * Voici la définition de estrtura.  * /
     /* Somente depois disso é que o com- */ données int / * Seulement après cela, avec-* /
     21 ] ; /* pilador vai saber como alocá-la. int texte [21] / * pilador saura de la renvoyer.  * /
 /* Tente um sizeof(my_type) no main. ;} / * Essayez un sizeof (my_type) en principal.  * /

 my_type ** my_ptr ) { /* some code... nulle create_my_type (** my_type my_ptr) {/ * un peu de code ...  * /}
 my_type ** my_ptr ) { /* some code... nulle destroy_my_type (** my_type my_ptr) {/ * un peu de code ...  * /}
 my_type * my_ptr , int d ) { /* some code... set_data void (* my_type my_ptr, int d) {/ * un peu de code ...  * /}
 my_type * my_ptr ) { /* some code... int get_data (my_type my_ptr *) {/ * un peu de code ...  * /}
 my_type * my_ptr , const char * text ) { /* some code... nulle set_text (my_type my_ptr *, const char * texte) {/ * un peu de code ...  * /}
 get_text ( my_type * my_ptr ) { /* some code... get_text char * (* my_type my_ptr) {/ * un peu de code ...  * /} 

L'exemple de code source complet peut être trouvé ici .

Puisque vous ne pouvez pas créer directement ces variables, nous avons besoin de définir un «constructeur» et un «destructeur».

Les tentatives d'accès direct aux membres de générer une erreur de compilation:

  private-struct-members$ gcc -o teste mytype.h mytype.c main.c user @ host: ~ / private-struct-membres: $ gcc-o test main.c mytype.h mytype.c
 main.c: In function 'main':
 main.c: 22: erreur: déréférencement pointeur de type incomplet
 private-struct-members$ user @ host: ~ / private-struct-membres $ 

Ainsi, avec un peu de créativité et avec les concepts des deux paradigmes linguistiques, il est possible d'appliquer des codes vraiment intéressant. Dans cet exemple idiot peut-être pas évident de l'utilité de forcer un logiciel d'émulation ou de l'utilisation de constructeur / destructeur en C, mais dans les systèmes où les circonstances ne permettent pas un C + +, ou la complexité tend à atteindre des niveaux critiques, ces techniques sont montrent d'une grande valeur. Dans notre cas, cette technique spécifiquement autorisé un programmeur expérimenté qui n'a pas assisté l'ensemble du projet, a découvert que sa tentative d'accéder directement à un membre d'une structure, a été inappropriée au contexte. Sans elle, une logique bug Kaboul semble qu'à l'exécution, ce qui rend le logiciel sans doute exploser dans le visage du client.

Liens utiles (ou pas ...):
http://www.directfb.org
http://www.caloni.com.br
http://www.numaboa.com.br/informatica/c/
Livre de développement du noyau Linux

Commentaires

  • Diogo V. Kersting

    Où puis-je télécharger le code source?
    http://blabos.org/blog/wp-content/uploads/2008/02/stopwatch.zip

  • bavarder

    Bonne nuit

    Merci pour votre attention.

    J'ai été changer le serveur de blog et certains ont fini par les liens brisés. Je vais corriger cela.

    Étreintes

  • bavarder

    Comme promis, il est là

    Étreintes

  • bavarder
  • Rodrigo Martins (sorcière)

    Il est temps d'afficher quelque chose de nouveau hein AHHuahuAHUahuA

  • bavarder

    Sorcière Oui, vous avez raison, mais l'os normal ...

    Heureusement, j'ai quelque chose dans le four :)

    Étreintes

  • Carcara

    Vous pouvez également masquer des unités de compilation avec des fonctions externes déclarant statique - Cela est également vrai pour les variables globales. Ainsi le lecteur externe ne sera pas connaître l'existence et la fonction statique éviter qu'il ne soit déclarée comme externe dans un autre fichier.

commentaires du blog propulsé par Disqus