Structure d’un object C ++ en mémoire avec une structure

Si j’ai un cours 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 example_struct 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)); 

foo_struct.x = 8 et foo_struct.y = 9 (c’est-à-dire: les mêmes valeurs que les valeurs x, y dans la classe 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 object avec du code C et je veux utiliser une structure pour représenter l’object provenant de la bibliothèque C ++. Je ne m’intéresse qu’aux atsortingbuts de l’object.

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

Le standard C ++ garantit que les dispositions de mémoire d’une struct C et d’une class C ++ (ou struct – même chose) seront identiques, à condition que la class / struct C ++ corresponde au critère de POD (“Plain Old Data”). Alors, que signifie POD?

Une classe ou une structure est POD si:

  • Tous les membres de données sont publics et sont eux-mêmes des types POD ou fondamentaux (mais pas des types de référence ou de pointeur sur membre), ou des tableaux de ce type.
  • Il n’a pas de constructeur, d’opérateur d’affectation ou de destructeur défini par l’utilisateur
  • Il n’a pas de fonctions virtuelles
  • Il n’a pas de classes de base

Les seules fonctions “C ++” autorisées sont les fonctions membres non virtuelles, les membres statiques et les fonctions membres.

Comme votre classe a à la fois un constructeur et un destructeur, il ne s’agit pas de type POD, donc la garantie ne tient pas. (Bien que, comme d’autres l’ont mentionné, dans la pratique, les deux dispositions sont probablement identiques sur tous les compilateurs que vous essayez, tant qu’il n’ya pas de fonctions virtuelles).

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

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.

Cela dit, la réponse est “oui, sur ma machine”, à condition que la classe 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”. Toutefois, si la classe possède des fonctions virtuelles (y compris un destructeur virtuel, qui pourrait être hérité d’une classe de base) ou utilise l’inheritance multiple, la disposition de la classe peut être différente.

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

Je suggère fortement un assert statique (vérification à la compilation) que sizeof (Example_class) == sizeof (example_struct) si vous faites cela. Voir BOOST_STATIC_ASSERT ou la construction spécifique au compilateur ou personnalisée. C’est un bon moyen 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 que les décalages par rapport aux membres sont les mêmes, ce qui (associé à la taille statique) garantira l’exactitude.

Les classes et structures en C ++ sont équivalentes, sauf que tous les membres d’une structure sont publics par défaut (les membres de la 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 atsortingbuer explicitement les membres de la classe aux structures lorsque vous souhaitez transmettre les données à C? De cette façon, vous savez que votre code fonctionnera partout.

Au début des compilateurs C ++, il y avait des exemples où le compilateur modifie d’abord les mots-clés de la structure avec la classe, puis les comstack. Tant de choses sur les similitudes.

Les différences proviennent de l’inheritance des classes et, en particulier, des fonctions virtuelles. Si la classe contient des fonctions virtuelles, elle doit avoir un pointeur sur le type de descripteur au début de sa mise en page. De plus, si la classe B hérite de la classe A, la mise en page de la classe A vient en premier, suivie de la propre disposition de la classe B.

Donc, 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 va probablement être la même. Si le destructeur devait être déclaré virtuel, la disposition deviendrait définitivement différente entre la structure et la 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 des fonctions virtuelles est introduite dans les classes qui ont des fonctions virtuelles: Leçon 4 – Polymorphisme

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