Question Quelle est la différence entre une définition et une déclaration?


Le sens des deux m'échappe.


707
2017-09-11 12:27


origine


Réponses:


UNE déclaration introduit un identifiant et décrit son type, qu'il s'agisse d'un type, d'un objet ou d'une fonction. Une déclaration est ce dont le compilateur a besoin accepter les références à cet identifiant. Ce sont des déclarations:

extern int bar;
extern int g(int, int);
double f(int, double); // extern can be omitted for function declarations
class foo; // no extern allowed for type declarations

UNE définition instancie / implémente cet identifiant. Ses ce dont le linker a besoin afin de lier les références à ces entités. Ce sont des définitions correspondant aux déclarations ci-dessus:

int bar;
int g(int lhs, int rhs) {return lhs*rhs;}
double f(int i, double d) {return i+d;}
class foo {};

Une définition peut être utilisée à la place d'une déclaration.

Un identifiant peut être déclaré aussi souvent que tu veux. Ainsi, ce qui suit est légal en C et C ++:

double f(int, double);
double f(int, double);
extern double f(int, double); // the same as the two above
extern double f(int, double);

Cependant, il doit être défini exactement une fois. Si vous oubliez de définir quelque chose qui a été déclaré et référencé quelque part, l'éditeur de liens ne sait pas à quoi associer les références et se plaint d'un symbole manquant. Si vous définissez quelque chose plus d'une fois, l'éditeur de liens ne sait pas lequel des définitions pour lier les références et se plaint des symboles dupliqués.


Depuis le débat qu'est-ce qu'une classe déclaration contre une classe définition en C ++ ne cesse de monter (dans les réponses et les commentaires à d'autres questions), je vais coller une citation de la norme C ++ ici.
A 3.1 / 2, C ++ 03 dit:

Une déclaration est une définition à moins qu'elle [...] ne soit une déclaration de nom de classe [...].

3.1 / 3 donne ensuite quelques exemples. Parmi eux:

[Exemple: [...]
struct S {int a; int b; } // définit S, S :: a, et S :: b [...]
struct S; // déclare S
-end exemple

Pour résumer: La norme C ++ considère struct x; être un déclaration et struct x {}; une définition. (En d'autres termes, "forward déclaration" un abus de langage, car il n'y a pas d'autres formes de déclarations de classe en C ++.)

Grâce à litb (Johannes Schaub) qui a creusé le chapitre et le verset dans une de ses réponses.


720
2017-09-11 12:43



De la section standard C ++ 3.1:

UNE déclaration introduit les noms dans une unité de traduction ou redéclare les noms introduits par les   déclarations. Une déclaration spécifie l'interprétation et les attributs de ces noms.

Le paragraphe suivant indique (soulignement le mien) qu'une déclaration est une définition sauf si...

... il déclare une fonction sans spécifier le corps de la fonction

void sqrt(double);  // declares sqrt

... il déclare un membre statique dans une définition de classe

struct X
{
    int a;         // defines a
    static int b;  // declares b
};

... il déclare un nom de classe

class Y;

... il contient le extern mot-clé sans un initialiseur ou un corps de fonction

extern const int i = 0;  // defines i
extern int j;  // declares j
extern "C"
{
    void foo();  // declares foo
}

... ou est un typedef ou using déclaration.

typedef long LONG_32;  // declares LONG_32
using namespace std;   // declares std

Maintenant, pour la grande raison pour laquelle il est important de comprendre la différence entre une déclaration et une définition: la Une règle de définition. De la section 3.2.1 de la norme C ++:

Aucune unité de traduction ne doit contenir plus d'une définition de variable, de fonction, de type de classe, de type d'énumération ou de modèle.


160
2017-09-11 13:53



Déclaration: "Quelque part, il existe un foo."

Définition: "... et c'est ici!"


111
2017-09-11 18:20



Il y a des cas intéressants en C ++ (certains d'entre eux en C aussi). Considérer

T t;

Cela peut être une définition ou une déclaration, selon le type T est:

typedef void T();
T t; // declaration of function "t"

struct X { 
  T t; // declaration of function "t".
};

typedef int T;
T t; // definition of object "t".

En C ++, lors de l'utilisation de modèles, il existe un autre cas de bordure.

template <typename T>
struct X { 
  static int member; // declaration
};

template<typename T>
int X<T>::member; // definition

template<>
int X<bool>::member; // declaration!

La dernière déclaration était ne pas une définition. C'est la déclaration d'une spécialisation explicite du membre statique de X<bool>. Il dit au compilateur: "S'il s'agit d'instancier X<bool>::member, puis n'instanciez pas la définition du membre du modèle principal, mais utilisez la définition trouvée ailleurs. "Pour en faire une définition, vous devez fournir un initialiseur

template<>
int X<bool>::member = 1; // definition, belongs into a .cpp file.

43
2017-09-11 18:15



Déclaration

Les déclarations indiquent au compilateur qu'un   l'élément de programme ou le nom existe. UNE   déclaration introduit un ou plusieurs   noms dans un programme. Les déclarations peuvent   se produire plus d'une fois dans un programme.   Par conséquent, les classes, les structures,   types énumérés, et d'autres   les types définis par l'utilisateur peuvent être déclarés pour   chaque unité de compilation.

Définition

Les définitions spécifient quel code ou quelles données   le nom décrit. Un nom doit être   déclaré avant qu'il peut être utilisé.


29
2017-09-11 12:35



De la norme C99, 6.7 (5):

Une déclaration spécifie l'interprétation et les attributs d'un ensemble d'identifiants. UNE définition d'un identifiant est une déclaration pour cet identifiant qui:

  • pour un objet, le stockage est réservé à cet objet;
  • pour une fonction, inclut le corps de la fonction;
  • pour une constante d'énumération ou un nom typedef, est la déclaration (seulement) de identifiant.

De la norme C ++, 3.1 (2):

Une déclaration est un définition sauf s'il déclare une fonction sans spécifier le corps de la fonction, il contient le spécificateur extern ou une spécification de liaison, ni un initialiseur ni un corps de fonction, il déclare un membre de données statiques dans une déclaration de classe, c'est une déclaration de nom de classe c'est une déclaration typedef, une déclaration d'utilisation ou une directive using.

Ensuite, il y a quelques exemples.

Tellement intéressant (ou pas, mais je suis légèrement surpris par ça), typedef int myint; est une définition en C99, mais seulement une déclaration en C ++.


18
2017-09-11 14:03



De wiki.answers.com:

Le terme déclaration signifie (en C) que vous dites au compilateur sur le type, la taille et en cas de déclaration de fonction, le type et la taille de ses paramètres de n'importe quelle variable, ou le type ou la fonction définie par l'utilisateur dans votre programme. Non l'espace est réservé en mémoire pour toute variable en cas de déclaration. Cependant le compilateur sait combien d'espace à réserver au cas où une variable de ce type est créée.

par exemple, voici toutes les déclarations:

extern int a; 
struct _tagExample { int a; int b; }; 
int myFunc (int a, int b);

La définition d'un autre côté signifie qu'en plus de tout ce que fait cette déclaration, l'espace est également réservé en mémoire. Vous pouvez dire "DEFINITION = DECLARATION + RESERVATION DE L'ESPACE" en suivant des exemples de définition:

int a; 
int b = 0; 
int myFunc (int a, int b) { return a + b; } 
struct _tagExample example; 

voir Réponses.


12
2017-09-11 12:30



Mise à jour C ++ 11

Puisque je ne vois pas de réponse pertinente à C ++ 11, en voici une.

Une déclaration est un définition sauf s'il déclare un / n:

  • enum opaque - enum X : int;
  • paramètre de modèle - T dans template<typename T> class MyArray;
  • déclaration de paramètre - X et y dans int add(int x, int y);
  • déclaration d'alias - using IntVector = std::vector<int>;
  • déclaration statique d'affirmation - static_assert(sizeof(int) == 4, "Yikes!")
  • déclaration d'attribut (définie par l'implémentation)
  • déclaration vide ;

Clauses supplémentaires héritées de C ++ 03 par la liste ci-dessus:

  • déclaration de fonction - ajouter dans int add(int x, int y);
  • spécificateur externe contenant une déclaration ou un spécificateur de liaison - extern int a; ou extern "C" { ... };
  • membre de données statiques dans une classe - X dans class C { static int x; };
  • classe / struct déclaration - struct Point;
  • déclaration typedef - typedef int Int;
  • utilisant la déclaration - using std::cout;
  • en utilisant la directive - using namespace NS;

Une déclaration de modèle est une déclaration. Une déclaration de modèle est également une définition si sa déclaration définit une fonction, une classe ou un membre de données statiques.

Exemples de la norme qui différencie la déclaration et la définition que j'ai trouvé utile pour comprendre les nuances entre eux:

// except one all these are definitions
int a;                                  // defines a
extern const int c = 1;                 // defines c
int f(int x) { return x + a; }          // defines f and defines x
struct S { int a; int b; };             // defines S, S::a, and S::b
struct X {                              // defines X
    int x;                              // defines non-static data member x
    static int y;                       // DECLARES static data member y
    X(): x(0) { }                       // defines a constructor of X
};
int X::y = 1;                           // defines X::y
enum { up , down };                     // defines up and down
namespace N { int d; }                  // defines N and N::d
namespace N1 = N;                       // defines N1
X anX;                                  // defines anX


// all these are declarations
extern int a;                           // declares a
extern const int c;                     // declares c
int f(int);                             // declares f
struct S;                               // declares S
typedef int Int;                        // declares Int
extern X anotherX;                      // declares anotherX
using N::d;                             // declares N::d


// specific to C++11 - these are not from the standard
enum X : int;                           // declares X with int as the underlying type
using IntVector = std::vector<int>;     // declares IntVector as an alias to std::vector<int>
static_assert(X::y == 1, "Oops!");      // declares a static_assert which can render the program ill-formed or have no effect like an empty declaration, depending on the result of expr
template <class T> class C;             // declares template class C
;                                       // declares nothing

12
2018-06-26 19:43