2017-10-05 5 views
2

Dans la documentation de l'API de SDL pour le Union event il est dit que le type de champ est partagé entre tous les événements (objets) dans l'Union, comment est-ce possible?Les syndicats et le partage des champs de données (C++)

également par exemple ceci est parfaitement légal

while(SDL_PollEvent(&event)){ 

    if(event.type == SDL_KEYDOWN){ 


    cout << "key down" << endl; 
    } 

et c'est fonctionne aussi ce qui rend logiquement plus de sens pour moi, mais je ne sais pas comment le premier est même légal

while(SDL_PollEvent(&event)){ 

    if(event.key.type == SDL_KEYDOWN){ 


     cout << "key down" << endl; 
    } 
+0

Ne pas oublier de marquer la bonne réponse (en utilisant la case), une fois que vous êtes satisfait. – BTownTKD

Répondre

1

un syndicat a le potentiel de représenter un sur multiples possibles types/structures.

union { 
    int i; 
    float f; 
    char c; 
}; 

Dans l'exemple ci-dessus, la mémoire qui détient le syndicat peut représenter une intou un floatou un char. Mais il ne peut être un de ces choses; ils sont mutuellement exclusifs. L'union chevauche les octets sous-jacents utilisés par chaque membre afin de gagner de l'espace et suppose que vous saurez comment l'interpréter correctement.

(Note latérale: pour tenir compte de cela, la «taille» de l'union - le nuage d'octets dans lequel l'union est stockée - doit être suffisamment grande pour contenir le plus grand type possible défini dans l'union. int ou float peut être de 4 octets chacun, donc l'union sera d'au moins 4 octets.)

Un effet secondaire net de cette «astuce» de mémoire qui se chevauche; Si une union décrit plusieurs membres struct, ils peuvent partager des champs communs.

Exemple:

union { 
    struct { 
    int type; 
    int i; 
    } OPTION_INT; 

    struct { 
    int type; 
    float f; 
    } OPTION_FLOAT; 

    struct { 
    int type; 
    char c; 
    } OPTION_CHAR; 
}; 

Bon, propre; l'union pourrait représenter l'un des trois structs possibles. Remarquez, cependant; ils contiennent tous exactement le même premier membre - type. En raison de la façon dont la mémoire est « chevauché », les parts membres OPTION_INT type la même mémoire que le OPTION_FLOAT et OPTION_CHAR type membres. Ainsi, quelle que soit l'option correcte, le membre type doit toujours exister. Ceci est possible parce qu'ils définissent tous le champ type comme membre premier.

+0

wow merci, réponse détaillée étonnante très appréciée =), cela fait beaucoup de sens – irishmaniac

+0

Alors que le truc soigné va probablement fonctionner, il ne doit pas en C++ et n'est pas garanti pour fonctionner. Pour de meilleurs résultats [coller aux types de POD] (http://en.cppreference.com/w/cpp/concept/PODType) et si cela doit absolument fonctionner, même dans le cas où les concepteurs du compilateur font l'inattendu, supprimez 'type 'depuis le' struct's interne et envelopper le 'union' dans un' struct' qui contient 'type'. – user4581301

+0

Je remets en question cette affirmation; il est * certainement * garanti en C - il y a une clause spéciale sur les membres initiaux communs d'une union dans la spécification de langage - mais je ne connais pas assez la spécification C++ pour savoir si cette clause est manquante. Ma compréhension était que C est un sous-ensemble complet de C++, ce qui suggère que la même garantie existe en C++. – BTownTKD

0

syndicats - dois love'em :) Il n'y a pas vraiment d'équivalent en Java, tant de développeurs Java à trouver particulière. Une union est conceptuellement un peu comme une classe abstraite - un seul syndicat peut contenir différents types de données. Les types de données ont souvent une sorte de relation d'héritage parent-enfant - ce qu'ils font dans le cas - mais ils ne sont pas tenus de le faire. Il n'est pas inhabituel, par exemple, de voir une union constituée d'un entier et d'un double - dans ce cas, ce n'est pas une structure de données contenant un entier et un double, mais un qui contient soit un entier ou un double, dans un morceau de mémoire spécifique. Le type réellement utilisé doit être déterminé au moment de l'exécution.

Dans ce cas, l'union SDL_Event modélise plusieurs types d'événements. Le premier champ, type indique comment le reste des données doit être interprété. Si le type est SDL_KEYDOWN, l'union doit être interprétée comme une structure de type SDL_KeyboardEvent.Le premier champ de SDL_KeyboardEvent est également type - ce qui est logique car il est compressé dans le même espace que le SDL_Event "de base". Vous pouvez penser à type (un peu) comme un attribut de la base "SDL_Event", qui peut être (en quelque sorte) héritée par les sous-types spécifiques. Je suis un peu louche ici, parce que l'analogie n'est pas vraiment très forte.

Dans tous les cas, le compilateur s'assurera que SDL_Event est assez grand pour stocker les différentes structures qu'il contient. Mis à part type, les structures spécifiques SDL_DropEvent, SDL_KeyboardEvent, etc., n'ont pas beaucoup en commun, comme on peut le voir en regardant leurs définitions.

En Java AWT, classes d'événements effectuent presque exactement le même rôle que l'union fait SDL_Event dans SDL avec C.

+0

Merci Kevin réponse détaillée superbe =) qui a un sens maintenant, ouais c'est très différent de Java, mais je pense que c'est assez cool concept – irishmaniac