Je l’ai vu pour vérifier si un type T
est une classe que je peux utiliser:
bool isClass = std::is_class::value;
Il renvoie true pour les classes et les structures. Je sais qu’en C ++ ils sont presque la même chose, mais j’aimerais savoir pourquoi il n’y a pas de distinction entre eux dans le trait de type. Est-il toujours inutile de vérifier cette différence, ou y a-t-il une raison supplémentaire que je ne comprends pas?
Il renvoie true pour les classes et les structures. Je sais qu’en C ++ ils sont presque la même chose, mais j’aimerais savoir pourquoi il n’y a pas de distinction entre eux dans le trait de type.
Malheureusement, c’est une idée fausse courante en C ++. Parfois, il s’agit d’un malentendu fondamental, mais parfois, il vient d’une ambiguïté en anglais. Cela peut provenir de diagnostics inexacts du compilateur, de livres mal écrits, de réponses SO incorrectes…
Vous avez probablement lu quelque chose comme ceci:
“Il n’y a pas de différence en C ++ entre une structure et une classe sauf la visibilité par défaut des membres et des bases.”
Ce passage peut être interprété dans un sens qui induit en erreur, car les notions d’ identité et d’ égalité sont difficiles à distinguer lorsque l’on utilise des expressions comme «pas de différence».
En fait, C ++ n’a pas de structure depuis 1985. Il n’a que des classes.
Le type de types que vous déclarez avec la class
mots-clés et le mot struct
clé struct
sont des classes . Période. Le mot clé struct
et les règles de visibilité par défaut lors de la définition d’une classe à l’aide de ce mot clé n’ont été conservés que pour la compatibilité avec C… mais c’est une syntaxe. Cela ne rend pas les types résultants réellement différents.
Le trait de type ne fait aucune distinction car il n’y a littéralement personne à faire.
Il est impossible de distinguer une différence de sémantique pour des définitions vides comme
class C { public: };
de
struct S { };
ou similaire
class C { };
et
struct S { private: };
En dehors du mot class
clé struct
vs class
, il n’y a pas de différence de comportement détectable. Voir aussi cette Q & A.
Remarque : Comme l’a fait remarquer @KyleStrand, la dérivation nécessite également des spécificateurs d’access explicites, donc S : private Base {};
et C : Base {};
sont équivalents, identiques à S : Base {};
et C : public Base {};
, où S
est une structure, C
est une classe et Base
peut être soit.
Ils sont la même chose. La seule différence (visibilité des membres par défaut) n’existe qu’au moment de la compilation. Il n’y a pas d’autre différence entre struct
et class
.
ETA: Ce que vous voulez probablement, c’est std::is_pod
, qui vous dira si votre classe est un “ancien type de données”. Une grande partie de la discussion et des commentaires sur cette question semble indiquer que c’est ce que veulent réellement ceux qui pensent qu’il devrait y avoir une distinction.
D’autres ont souligné correctement qu’en C ++, les mots struct
clés struct
et class
ont la même signification, à l’exception de la visibilité des membres.
Que vous appeliez des types d’agrégats ainsi définis “structs” ou “classes” ou “weiruewzewiruz” vous appartient. Dans l’intérêt de la communication, il est généralement conseillé de suivre les conventions établies, alors je déconseille de “weiruewzewiruz”.
Il est également recommandé d’utiliser les différences sémantiques comme guide pour les choix de mots. L’utilisation de struct
est plus courante pour les données agrégées simples qui n’ont pas beaucoup de logique interne et d’invariants; une utilisation typique serait struct point { float x; float y; };
struct point { float x; float y; };
. De tels types sont souvent appelés “structures” ou “structures” dans la littérature. Il ne serait pas surprenant que quelqu’un utilisant fprintf
en C ++ fasse référence au premier argument en tant que “pointeur sur une structure FILE”. FILE est un exemple de ce que Scott Meyers veut dire dans “More effective C ++”, article 34:
Il est prudent de supposer qu’une définition de structure qui comstack dans les deux langages [C et C ++ -pas] est conçue de la même manière par les deux compilateurs.
En ce qui concerne le langage naturel, le mot choix “structure” n’est pas une coïncidence: Meyers parle d’un ancien agrégat de données simple qui a une sémantique identique dans les deux langues, jusqu’au niveau des bits.
Concernant le langage de programmation, cela n’aurait pas d’importance si la définition C ++ de l’agrégat de données en question utilisait le mot struct
clé struct
ou class
(avec un spécificateur d’access public). struct
est peut-être le choix le plus naturel, car la sémantique C ++ de l’agrégat est la sémantique d’une structure en C. De plus, l’utilisation de struct
permet aux sources C et C ++ de partager plus facilement une définition de type.
Le standard C ++ utilise “struct” et “structure” à la fois en langage naturel et en langage de programmation, pas seulement en cas d’interopérabilité: 1.7 / 5: “Une structure déclarée en tant que” ou 3.2 / 4 struct X; // declare X as a struct type
struct X; // declare X as a struct type
. Le plus intéressant est le 9/8, posant les bases de l’interopérabilité:
8 Une structure de présentation standard est une classe de présentation standard définie avec la structure class-key ou la classe class-key. […]
Comment quelqu’un qui lit ceci peut-il prétendre qu’il n’y a pas de struct en C ++? Ce n’est clairement pas une erreur de assembly car les termes “struct” et “class” sont explicitement définis les uns par rapport aux autres.
Les différences manifestes et vérifiables sont toutefois plus intéressantes que les choix de mots et les questions de goût. Dans quelles circonstances un agrégat C ++ est-il comparable et compatible avec une struct
C? Peut-être que cette question était à la base de votre question? La disposition standard mentionnée dans le devis est le critère. Il est détaillé dans 9/7 et prescrit essentiellement que
La norme dit alors
9 [Remarque: les classes de présentation standard sont utiles pour communiquer avec du code écrit dans d’autres langages de programmation. Leur mise en page est spécifiée au 9.2. – note finale]
Bien entendu, une définition de structure qui comstack en C remplit ces critères, d’où l’assertion de Scott Meyers. FILE
de stdio.h est un exemple important, pas tout à fait sortingvial. Notez que la norme ne garantit pas, car la mise en page des objects dépend de l’implémentation et peut changer uniquement avec une option du compilateur.
Si une classe a une présentation standard peut être testée avec le type trait std::is_standard_layout
. Le programme suivant, inspiré d’ un exemple de cppreference , vérifie les principaux cas exposés dans la norme.
#include #include #include using namespace std; struct funcOnlyT // fine { int f(); }; class podT { // "class" is ok int m1; int m2; }; struct badAccessCtrlT { // bad: public/private int m1; private: int m2; }; struct polymorphicT { // bad: polymorphic int m1; int m2; virtual void foo(); }; struct inheritOkT: podT // ok: inheritance, data only on one level { int f(); }; struct inheritPlusDataT: podT // bad: inheritance, data on 2 levels { int m3; }; template struct templT // ok with std layout types T1, T2 { T1 m1; T2 m2; }; // print type "name" and whether it's std layout template void printIsStdLayout() { printf("%-20s: %s\n", typeid(T).name(), std::is_standard_layout::value ? "is std layout" : "is NOT std layout"); } int main() { printIsStdLayout(); printIsStdLayout(); printIsStdLayout(); printIsStdLayout(); printIsStdLayout(); printIsStdLayout(); printIsStdLayout >(); printIsStdLayout(); }
Exemple de session:
$ g++ -std=c++11 -Wall -o isstdlayout isstdlayout.cpp && ./isstdlayout 9funcOnlyT : is std layout 4podT : is std layout 14badAccessCtrlT : is NOT std layout 12polymorphicT : is NOT std layout 10inheritOkT : is std layout 16inheritPlusDataT : is NOT std layout 6templTIifE : is std layout 9__sFILE64 : is std layout
C ++ 11 §9 / 8 ([classe] / 8) :
” Une structure de disposition standard est une classe de présentation standard définie avec la
struct
class-key ou la classe class-key . Une union de présentation standard est une classe de présentation standard définie avec l’union
clé de classe .
C ++ 11 §9 / 10 ([classe] / 10) :
” Une structure POD est une classe non-union qui est à la fois une classe sortingviale et une classe de présentation standard et ne comporte aucun membre de données non statique de type non-POD, union non-POD (ou tableau de ce type). […]
Comme une structure POD est une classe de disposition standard, il s’agit d’un sous-ensemble de la structure de présentation standard . Pour autant que je sache, c’est la signification la plus générale de struct dans le standard C ++. Et donc, ce que vous recherchez est probablement un trait de type ou un ensemble de traits de caractères qui vous permettent d’identifier une structure de présentation standard en tant que telle.
Et voilà, en regardant la liste des caractères, il y a is_class
et is_standard_layout
. Quand un type satisfait à la fois c’est une structure. Ou plus précisément, c’est une structure de format standard , telle que définie par C ++ 11 §9 / 8.
En ce qui concerne
“ J’aimerais savoir pourquoi il n’y a pas de distinction entre [class et struct] dans le trait de type
Eh bien, il y en a. C’est le trait is_standard_layout
.
En ce qui concerne
« Est-il toujours inutile de vérifier cette différence, ou y a-t-il une raison supplémentaire que je ne comprends pas?
Non, il n’est pas inutile de vérifier cette différence. La norme définit la présentation standard pour la raison qu’elle est très pratique. Comme l’indique la norme elle-même,
C ++ 11 §9 / 9 ([classe] / 9) :
” [Remarque: les classes de présentation standard sont utiles pour communiquer avec du code écrit dans d’autres langages de programmation. Leur mise en page est spécifiée au 9.2. – note finale]
Remarques:
¹ Le trait is_class
est vrai pour une class
ou une struct
, mais pas pour une union
, même si la norme définit «une union est une classe». Ie trait est plus spécifique que la terminologie générale.