C / C ++ Struct vs classe

108

Après avoir terminé ma classe C ++, il m'a semblé que les structures / classes sont pratiquement identiques, sauf avec quelques différences mineures.

Je n'ai jamais programmé en C avant; mais je sais qu'il a des structures. En C est-il possible d'hériter d'autres structures et de définir un modificateur de public / private?

Si vous pouvez faire cela en C normal, pourquoi avons-nous besoin de C ++? Qu'est-ce qui différencie les classes d'une structure?


la source

Réponses:

146

En C ++ , les structures et les classes sont à peu près les mêmes; la seule différence est que lorsque les modificateurs d'accès (pour les variables membres, les méthodes et les classes de base) dans les classes sont par défaut privés, les modificateurs d'accès des structures par défaut sont publics.

Cependant, en C , une structure est juste une collection agrégée de données (publiques), et n'a pas d'autres fonctionnalités de type classe: pas de méthode, pas de constructeur, pas de classes de base, etc. Bien que C ++ ait hérité du mot-clé, il a étendu la sémantique. (Ceci, cependant, est la raison pour laquelle les choses par défaut sont publiques dans les structures - une structure écrite comme une structure C se comporte comme une.)

Bien qu'il soit possible de simuler une certaine POO en C - par exemple, définir des fonctions qui prennent toutes un pointeur vers une structure comme premier paramètre, ou forcer occasionnellement des structures avec les mêmes premiers champs à être des "sous / superclasses" - c'est toujours en quelque sorte boulonné, et ne fait pas vraiment partie de la langue.

Antal Spector-Zabusky
la source
À partir de la POO, les gens potentiels .Net l'ont défini de cette façon ✓ CONSIDERER à définir une structure au lieu d'une classe si les instances du type sont petites et généralement de courte durée ou sont généralement intégrées dans d'autres objets. X ÉVITEZ de définir une structure à moins que le type ne possède toutes les caractéristiques suivantes: 1. Il représente logiquement une valeur unique, similaire aux types primitifs (int, double, etc.). 2. Il a une taille d'instance inférieure à 16 octets. 3. Il est immuable.
Abhijeet
5
@Abhijeet C'est la distinction entre les structures et les classes en C #, mais ce n'est tout simplement pas pertinent pour C ++, et encore plus pour C. En C #, les classes et les structures sont en fait différentes; ce n'est pas le cas en C ++, et C n'a que des structures sans OO.
Antal Spector-Zabusky
ne serait-il pas préférable de garder la même sémantique C dans la structure C ++? et quand il est nécessaire d'utiliser une "structure de manière c ++", utilisez simplement une classe? Je n'ai jamais eu l'avantage d'avoir une structure "augmentée" en C ++ par rapport à C. J'aime toujours utiliser la structure telle qu'elle a été conçue en C, sinon utilisez une classe, avec quelques exceptions autorisées.
Raffaello
15

Autre que les différences dans l'accès par défaut (public / privé), il n'y a pas de différence.

Cependant, certains magasins qui codent en C et C ++ utiliseront "class / struct" pour indiquer ce qui peut être utilisé en C et C ++ (struct) et qui sont uniquement en C ++ (class). En d'autres termes, dans ce style, toutes les structures doivent fonctionner avec C et C ++. C'est en quelque sorte la raison pour laquelle il y avait une différence à l'origine il y a longtemps, à l'époque où C ++ était encore connu sous le nom de «C avec classes».

Notez que les unions C fonctionnent avec C ++, mais pas l'inverse. Par exemple

union WorksWithCppOnly{
    WorksWithCppOnly():a(0){}
    friend class FloatAccessor;
    int a;
private:
    float b;
};

Et également

typedef union friend{
    int a;
    float b;
} class;

ne fonctionne qu'en C

Lance Diduck
la source
9
Utiliser des mots-clés cpp dans votre code c puis prétendre qu'il n'est pas compatible cpp est plutôt stupide
Dani
7

Je vais ajouter aux réponses existantes car le C ++ moderne est maintenant une chose et des directives de base officielles ont été créées pour aider avec des questions comme celles-ci.

Voici une section pertinente des directives:

C.2: Utiliser la classe si la classe a un invariant; utiliser struct si les données membres peuvent varier indépendamment

Un invariant est une condition logique pour les membres d'un objet qu'un constructeur doit établir pour que les fonctions membres publiques prennent en charge. Une fois l'invariant établi (généralement par un constructeur), chaque fonction membre peut être appelée pour l'objet. Un invariant peut être indiqué de manière informelle (par exemple, dans un commentaire) ou plus formellement en utilisant Expects.

Si tous les membres de données peuvent varier indépendamment les uns des autres, aucun invariant n'est possible.

Si une classe a des données privées, un utilisateur ne peut pas complètement initialiser un objet sans l'utilisation d'un constructeur. Par conséquent, le définisseur de classe fournira un constructeur et doit spécifier sa signification. Cela signifie effectivement que le définisseur doit définir un invariant.

Mise en vigueur

Recherchez des structures avec toutes les données privées et des classes avec des membres publics.

Les exemples de code donnés:

struct Pair {  // the members can vary independently
    string name;
    int volume;
};

// but

class Date {
public:
    // validate that {yy, mm, dd} is a valid date and initialize
    Date(int yy, Month mm, char dd);
    // ...
private:
    int y;
    Month m;
    char d;    // day
};

Classes fonctionnent bien pour les membres qui sont, par exemple, dérivés les uns des autres ou interdépendants. Ils peuvent également aider à vérifier la cohérence lors de l'instanciation. Structs fonctionnent bien pour avoir des «sacs de données», où rien de spécial ne se passe vraiment mais où les membres ont logiquement un sens à être regroupés.

À partir de là, il est logique que classes existent pour prendre en charge l'encapsulation et d'autres concepts de codage associés, pour lesquels les structs ne sont tout simplement pas très utiles.

Dave
la source
Une autre considération est la portabilité. structs sont les plus portables. Ils peuvent être utilisés en C ou C ++ ou dans les deux sens. Ils peuvent également être décompressés en Python à l'aide du structmodule, par exemple. Si votre projet établit les priorités de compatible avec d' autres langues, interfaces ou systèmes, préfèrent structplus class. Pour les affaires strictement internes au programme, préférez class.
Dave
6

Il n'est pas possible de définir des fonctions membres ou de dériver des structures les unes des autres en C.

En outre, C ++ n'est pas seulement C + "dériver des structures". Les modèles, les références, les espaces de noms définis par l'utilisateur et la surcharge d'opérateurs n'existent pas tous dans C.

Johannes Schaub - litb
la source
Je sais que les modèles, etc. n'existent pas en C mais je n'étais pas au courant powerdes structures de C. Donc, C ++ utilise uniquement des structures pour être «rétrocompatible» avec C?
4
Juste pour la compatibilité ascendante? Sur une base pratique, il y a probablement quelque chose à cela, mais la distinction peut être un signal d'intention: là où j'utilise un, structje veux dire un type de chose de type POD largement passif.
dmckee --- ex-moderator chaton
@dmckee: Pour ce que ça vaut, la plupart des foncteurs STL (ie std::less) sont définis comme des structures, pas comme des classes.
Billy ONeal
1
C ++ n'est pas entièrement compatible avec C. On pourrait dire que le mot-clé struct est un accommodement pour les développeurs C. J'aime le mot-clé struct pour les classes qui contiennent simplement des données de manière ordonnée mais ne fournissent pas (beaucoup) de logique elles-mêmes.
ypnos
@ypnos: Voir mon dernier commentaire. La seule différence entre les deux est que les membres de l'un sont publics par défaut et les autres sont privés par défaut.
Billy ONeal
3

Une autre différence en C ++, lorsque vous héritez d'une classe de struct sans aucun spécificateur d'accès, cela devient l'héritage public où, comme dans le cas de la classe, c'est l'héritage privé.

MarsRover
la source
1

C ++ utilise principalement des structures pour 1) la compatibilité ascendante avec les types C et 2) POD. Les structures C n'ont pas de méthodes, d'héritage ou de visibilité.

Chris Hafey
la source
2
Pour ce que ça vaut, la plupart des foncteurs STL (ie std::less) sont définis comme des structures, pas comme des classes.
Billy ONeal
3
Notez que les structures C ++ ont des méthodes, un héritage et une visibilité.
robertwb
c struct peut inclure un pointeur de fonction en tant que type (* addr) (params);
Erreur