Privés des membres dans les structures C

18 mai 2008 · Posted in C / C + +

Cette semaine, ici au travail avait plus la preuve que paradigme de la programmation est un langage complètement indépendant, à savoir non pas par le fait que vous êtes la programmation en C + +, la compilation avec g + + votre code sera orienté objet si peu, si vous programmez en C ANSI votre code ne seront pas nécessairement structurées ou que vous ne pourrez pas la programmation orientée objet.

Je suis en train de lire, Orientation objet en C ANSI?

Oui et non!

Des choses comme l'héritage, le polymorphisme et la surcharge sont compliquées à faire / émuler en C, mais vous pouvez programmer en utilisant un style qui se comporte comme de la programmation objet. Le libdfb est écrit en C, mais "orienté objet", afin que vous créez, manipuler pour détruire des éléments qui se comportent de manière très similaire aux 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 en C a aussi été écrit (et très bien écrit, dire en passant) à ces techniques, en simulant une orientation objet. Une de ces techniques, j'ai été frappé à l'aide d'une de ces notes des livres de 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, à moins, il est dit encore dans d'autres unités comme extern. Ainsi, il est possible de "cacher" certains symboles au sein de l'unité de compilation, les rendant inaccessibles au monde extérieur. Nous avons avec ce paquet.

Une unité de compilation est l'ensemble des fichiers qui après le pré-traitement et d'établissement de générer un code objet unique. Essentiellement (mais pas exactement), on peut prendre pour chaque unité de compilation mise en œuvre du code source de fichier (*. c, *. cpp. Etc). De plus amples détails sur les étapes de compilation C et C + + peuvent être trouvés sur le Caloni blog.

En utilisant cette information, nous pouvons créer une structure en C ANSI dans laquelle ses membres internes sont «privées». La magie est dans la définition des membres de 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 un manifeste: le compilateur présente un identifiant sans dire beaucoup de sa signification, ou indiquer au compilateur que l'identificateur est XXX, mais on sait peu sur ce qu'il représente.
Par exemple

  a ; extern int a;
 void ) ; void blah (void);
 struct st_date; 

Définition et mise en œuvre: indique au compilateur que l'identificateur est déterminé, comme la quantité de mémoire doit être attribué, et quelle est l'adresse mémoire où on peut trouver, entre autres choses.
Par exemple

  int a;
 void ) { /* Do anything. blah (void) (/ * Ne rien.  * /)
 /* Some members. st_date struct (/ * Certains membres.  * /) 

Quand nous parlons des structures et des types, sans fixer le compilateur n'a aucun moyen d'allouer de la mémoire pour eux, car on ne sait rien sur la façon dont beaucoup d'espace une variable de ce type de besoin. D'un autre côté, parfois sans que la déclaration, le linker ne peut pas savoir que ce symbole existe.

Lorsque nous déclarons une structure dans un en-tête, généralement on définit également ses membres là-bas et chaque fois que nous ajoutons cette entête à une source de la nôtre, nous avons inclus dans l'unité de compilation comme la source de cette déclaration que la définition de cette structure, ce qui rend les membres du public interinstitutionalcollaboration à cette unité de compilation. Cela nous permet d'accéder à ses membres directement.

Si nous nous séparons à la déclaration de la définition, seul symbole qui représente la structure 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 de la taille de la structure, vous ne pouvez pas définir directement une variable de la structure, seulement un pointeur vers elle, parce que les pointeurs sont tous de la même taille et le compilateur n'a besoin que du nom du symbole type pour créer le pointeur.

Ensuite, nous avons quelque chose mytype.h-tête comme ceci:

  # Ifndef MY_TYPE_H
 # Define MY_TYPE_H

 / * Le typedef ne s'agit pas seulement de répéter le mot struct.  * /
 / * La déclaration est que ces mots: * /
 / * Struct _MYTYPE * /
 typedef struct my_type _MYTYPE;

 my_type ** ) ; void create_my_type (my_type **);
 my_type ** ) ; void destroy_my_type (my_type **);

 my_type * , int ) ; void set_data (my_type *, int);
 my_type * ) ; int get_data (my_type *);
 my_type * , const char * ) ; void set_text (my_type *, const char *);
 get_text ( my_type * ) ; char * get_text (my_type *);

 # Endif 

Mytype.c mise en œuvre:

 _mytype { /* Aqui fica a definição da estrtura. # Include "mytype.h" # include # include # include struct <string.h> _MYTYPE (/ * Voici la définition de estrtura.  data ; /* Somente depois disso é que o com-  */ int text [ 21 ] ; /* pilador vai saber como alocá-la. * / Int data; / * Seulement après cela, avec-* / int texte [21], / * pilador saura à son attribution.  ; /* Tente um sizeof(my_type) no main. * /), / * Essayez un sizeof (my_type) dans le principal.  create_my_type ( my_type ** my_ptr ) { /* some code... * / Create_my_type Void (my_type ** my_ptr) (/ * un peu de code ...  void destroy_my_type ( my_type ** my_ptr ) { /* some code... * /) Destroy_my_type Void (my_type ** my_ptr) (/ * un peu de code ...  void set_data ( my_type * my_ptr , int d ) { /* some code... * /) Set_data Void (my_type * my_ptr, int d) (/ * un peu de code ...  int get_data ( my_type * my_ptr ) { /* some code... * /) Get_data Int (my_type * my_ptr) (/ * un peu de code ...  void set_text ( my_type * my_ptr , const char * text ) { /* some code... * /) Set_text Void (my_type * my_ptr, const char * text) (/ * un peu de code ...  char * get_text ( my_type * my_ptr ) { /* some code... * /) Char * get_text (my_type * my_ptr) (/ * un peu de code ...  * /) 

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

Parce que vous ne pouvez pas créer directement les variables de ce type, on définit un «bâtisseur» et un destructeur ".

Les tentatives d'accès direct aux membres 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: Dans la fonction 'main':
 main.c: 22: erreur: déréférencement de pointeur de type incomplet
 private-struct-members$ user @ host: ~ / private-struct-membres $ 

Ainsi, avec un peu de créativité et avec les notions de la langue et les paradigmes, il est possible d'appliquer des codes vraiment intéressant. Dans cet exemple simpliste pourrait ne pas avoir été clair sur l'utilité de forcer un package d'émulation ou de l'utilisation du constructeur / destructeur en C, mais dans les systèmes où les circonstances ne permettent pas un C + +, ou de la complexité tend à atteindre des niveaux critiques, des techniques telles spectacle de grande valeur. Dans notre cas, cette technique est autorisé spécifiquement un programmeur expérimenté, n'a pas fait l'ensemble du projet, il a découvert que sa tentative d'accéder directement à un membre d'une structure, a été contextuellement inappropriée. Sans elle, une logique cabuloso bug semble qu'à l'exécution, rendant le logiciel sans doute exploser au 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

7 Responses to "Les membres du privé dans les structures C"

  1. Diogo V. Kersting le 10 Juin, 2008 16:40

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

  2. blab le 10 Juin, 2008 23:12

    Bonne nuit,

    Je vous remercie de votre attention.

    J'ai changé le serveur de blog et que certains liens ont fini par être brisé. Je vais le résoudre.

    Hugs

  3. blab le 10 Juin, 2008 23:58

    Comme promis, là

    Hugs

  4. blab le 11 Juin, 2008 00:00
  5. Rodrigo Martins (Warlock) sur Juillet 15, 2008 01:30

    Il est temps de mettre quelque chose de nouveau hein AHHuahuAHUahuA

  6. jaser sur Juillet 15, 2008 09:09

    Witch Oui, vous avez raison, mais tá osso ...

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

    Hugs

  7. Carcara sur Octobre 27th, 2008 13:14

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

Laissez une réponse




Powered by WP Hashcash