43 votes

Le nom de la classe ne désigne pas un type en C++.

Je viens de commencer à programmer en C++, et j'ai essayé de créer 2 classes dont l'une contiendra l'autre.

Fichier A.h :

#ifndef _A_h
#define _A_h

class A{
    public:
        A(int id);
    private:
        int _id;
        B _b; // HERE I GET A COMPILATION ERROR: B does not name a type
};

#endif

Fichier A.cpp :

#include "A.h"
#include "B.h"
#include <cstdio>

A::A(int id): _id(id), _b(){
    printf("hello\n the id is: %d\n", _id);
}

Fichier B.h :

#ifndef _B_h
#define _B_h

class B{
    public:
        B();
};
#endif

Fichier B.cpp :

#include "B.h"
#include <cstdio>

B::B(){
    printf("this is hello from B\n");
}

Je compile d'abord la classe B, puis la classe A, mais j'obtiens ensuite le message d'erreur :

A.h:9 : error : 'B' ne désigne pas un type.

Comment puis-je résoudre ce problème ?

55voto

Björn Pollex Points 41424

Le préprocesseur insère le contenu des fichiers A.h y B.h exactement où le include se produit (il s'agit en fait d'un simple copier/coller). Lorsque le compilateur analyse ensuite A.cpp il trouve la déclaration de la classe A avant de connaître la classe B . Cela provoque l'erreur que vous voyez. Il y a deux façons de résoudre ce problème :

  1. Inclure B.h en A.h . C'est généralement une bonne idée d'inclure les fichiers d'en-tête dans les fichiers où ils sont nécessaires. Si vous comptez sur une inclusion indirecte à travers un autre en-tête, ou sur un ordre spécial d'inclusion dans l'unité de compilation (fichier cpp), cela ne fera que vous embrouiller, vous et les autres, au fur et à mesure que le projet grandira.
  2. Si vous utilisez une variable membre de type B en classe A le compilateur a besoin de connaître la déclaration exacte et complète de B parce qu'il doit créer la structure de la mémoire pour les éléments suivants A . Si, d'autre part, vous utilisiez un pointeur ou une référence à B Dans ce cas, une déclaration directe suffirait, car la mémoire que le compilateur doit réserver pour un pointeur ou une référence est indépendante de la définition de la classe. Cela ressemblerait à ceci :

    class B; // forward declaration        
    class A {
    public:
        A(int id);
    private:
        int _id;
        B & _b;
    };

    Ceci est très utile pour éviter les dépendances circulaires entre les en-têtes.

J'espère que cela vous aidera.

12voto

user3070485 Points 11
error 'Class' does not name a type

Juste au cas où quelqu'un ferait la même chose idiote que moi... Je créais un petit programme de test à partir de rien et j'ai tapé Classe au lieu de classe (avec un petit C). Je n'ai pas fait attention aux guillemets dans le message d'erreur et j'ai passé un peu trop de temps à ne pas comprendre mon problème.

Ma recherche d'une solution m'a amené ici, donc je suppose que la même chose peut arriver à quelqu'un d'autre.

6voto

Adarsh Chauhan Points 176

NOTE : Parce que les personnes effectuant une recherche avec le même mot clé atterriront sur cette page, j'ajoute cette réponse qui n'est pas la cause de cette erreur de compilation dans le cas mentionné ci-dessus.

J'étais confronté à cette erreur lorsque j'avais un enum déclarée dans un fichier dont l'un des éléments avait le même symbole que le nom de ma classe.

Par exemple, si je déclare un enum = {A, B, C} dans un fichier qui est inclus dans un autre fichier où je déclare un objet de type class A .

Cela a donné lieu au même message d'erreur du compilateur mentionnant que Class A does not name a type . Il n'y avait pas de dépendance circulaire dans mon cas.

Soyez donc prudent lorsque vous nommez des classes et déclarez des enums (qui peuvent être visibles, importés et utilisés en externe dans d'autres fichiers) en C++.

3voto

Puppy Points 90818

Vous devez d'abord inclure B.h de A.h . B b n'a aucun sens tant que vous n'avez pas inclus B.h .

2voto

Chubsdad Points 14310

Inclure "B.h" dans "A.h". Cela apporte la déclaration de 'B' pour le compilateur lors de la compilation de 'A'.

La première balle tient dans le cas de l'OP.

$3.4.1/7 -

"Un nom utilisé dans la définition d'une classe X en dehors d'une fonction membre d'un corps ou d'une définition de classe imbriquée27) doit être déclaré dans l'une des formes façons suivantes :

- avant son utilisation dans classe X ou être membre d'une classe de base de X (10.2), o

- si X est un classe de la classe Y (9.7), avant la définition de X dans Y, ou est un membre d'une classe de base de Y (cette recherche s'applique à son tour aux classes classes englobantes de Y, en commençant par la classe englobante la plus proche),28) ou

- si X est une classe locale (9.8) ou est une classe imbriquée d'une classe locale, avant la définition de la classe X dans un bloc entourant la définition de la classe X, ou

- si X est un membre de l'espace de noms N, ou est une classe imbriquée d'une classe qui est membre de N, ou est une classe locale ou une classe imbriquée dans une classe locale d'une fonction qui est membre de N, avant la définition de la classe X dans l'espace de noms N ou dans l'un des espaces de noms de N".

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X