Question

Si j'ai une classe comme suit

   class Example_Class 
   {
       private:
         int x; 
         int y; 
       public: 
         Example_Class() 
         { 
             x = 8;
             y = 9;
         }
       ~Example_Class() 
       { } 
   };

Et une structure comme suit

struct
{
   int x;
   int y;
} example_struct;

La structure en mémoire de exemple_struct est-elle identique à celle de Example_Class

par exemple si je fais ce qui suit

struct example_struct foo_struct;
Example_Class foo_class = Example_Class();

memcpy(&foo_struct, &foo_class, sizeof(foo_struct));

sera foo_struct.x = 8 et foo_struct.y = 9 (c'est-à-dire: les mêmes valeurs que les valeurs x, y dans la foo_class)?

La raison pour laquelle je pose la question est que j’ai une bibliothèque C ++ (je ne veux pas la changer) qui partage un objet avec du code C et je veux utiliser une structure pour représenter l’objet provenant de la bibliothèque C ++. Je ne m'intéresse qu'aux attributs de l'objet.

Je sais que la situation idéale serait d'avoir Example_class encapsulant une structure commune entre le code C et le code C ++, mais il ne sera pas facile de changer la bibliothèque C ++ utilisée.

Était-ce utile?

La solution

La norme C ++ garantit que les dispositions de mémoire d’une structure C struct et d’une classe C ++ (ou struct - - même chose) sera identique, à condition que la classe / struct C ++ du C ++ réponde au critère de POD ("Plain Old Data"). . Alors, que signifie POD?

Une classe ou une structure est un POD si:

  • Tous les membres de données sont des types POD ou fondamentaux du public et sont publics (mais pas des types référence ou pointeur vers membre), ni des tableaux de ce type
  • Il n'a pas de constructeur défini par l'utilisateur, ni d'opérateur d'affectation ni de destructeur
  • Il n'a pas de fonctions virtuelles
  • Il n'a pas de classes de base

À propos du seul " C ++ - isms " Sont autorisés les fonctions membres non virtuelles, les membres statiques et les fonctions membres.

Étant donné que votre classe a à la fois un constructeur et un destructeur, elle n’est formellement pas de type POD et la garantie ne tient donc pas. (Bien que, comme d'autres l'ont mentionné, dans la pratique, les deux présentations soient identiques sur tous les compilateurs que vous essayez, tant qu'il n'y a pas de fonctions virtuelles).

Voir la section [26.7] du C ++ FAQ Lite pour plus de détails.

Autres conseils

  

La structure en mémoire de example_struct est-elle identique à celle de Example_Class

Le comportement n'est pas garanti et dépend du compilateur.

Ceci étant dit, la réponse est "oui, sur ma machine", à condition que Example_Class ne contienne aucune méthode virtuelle (et n'hérite pas d'une classe de base).

Dans le cas que vous décrivez, la réponse est "probablement oui". Cependant, si la classe a des fonctions virtuelles (y compris un destructeur virtuel, qui pourrait être hérité d’une classe de base), ou utilise plusieurs héritages, la structure de la classe peut être différente.

Pour ajouter à ce que d'autres personnes ont dit (par exemple: spécifique au compilateur, fonctionnera probablement tant que vous n'avez pas de fonctions virtuelles):

Je suggérerais fortement une assertion statique (vérification à la compilation) que sizeof (Example_class) == sizeof (example_struct) si vous le faites. Voir BOOST_STATIC_ASSERT ou la construction équivalente spécifique au compilateur ou personnalisée. C'est une bonne première ligne de défense si quelqu'un (ou quelque chose, comme un changement de compilateur) modifie la classe pour invalider la correspondance. Si vous souhaitez une vérification supplémentaire, vous pouvez également vérifier à l'exécution que les décalages vers les membres sont les mêmes, ce qui (avec l'assertion de taille statique) garantira l'exactitude.

Aux débuts des compilateurs C ++, il existait des exemples lorsque le compilateur modifiait pour la première fois les mots-clés struct avec class puis compile. Tant de choses sur les similitudes.

Les différences proviennent de l'héritage de classe et, en particulier, des fonctions virtuelles. Si la classe contient des fonctions virtuelles, elle doit alors avoir un pointeur pour saisir le descripteur au début de sa présentation. De plus, si la classe B hérite de la classe A, la disposition de la classe A vient en premier, suivie de la disposition de la classe B.

La réponse précise à votre question sur la conversion d'une instance de classe en instance de structure est la suivante: dépend du contenu de la classe. Pour une classe particulière qui a des méthodes (constructeur et destructeur non virtuel), la disposition sera probablement la même. Si le destructeur était déclaré virtuel, la présentation deviendrait certainement différente entre structure et classe.

Voici un article qui montre qu'il n'y a pas grand chose à faire pour passer des structures C aux classes C ++: Leçon 1 - De la structure à la classe

Et voici l'article qui explique comment la table de fonctions virtuelles est introduite dans les classes comportant des fonctions virtuelles: Leçon 4 - Polymorphisme

Classes & amp; Les structures en C ++ sont équivalentes, sauf que tous les membres d'une structure sont publics par défaut (les membres de classe sont privés par défaut). Cela garantit que la compilation du code C hérité dans un compilateur C ++ fonctionnera comme prévu.

Rien ne vous empêche d'utiliser toutes les fonctionnalités C ++ sophistiquées d'une structure:

struct ReallyAClass
{
    ReallyAClass();
    virtual !ReallAClass();

    /// etc etc etc
};

Pourquoi ne pas assigner explicitement les membres de la classe à ceux de la structure lorsque vous souhaitez transmettre les données à C? De cette façon, vous savez que votre code fonctionnera n'importe où.

Vous venez probablement de dériver la classe de la structure, en public ou en privé. Ensuite, le résoudre serait résolu correctement dans le code C ++.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top