Имя класса не называет тип в С++
Я только начал программировать на С++, и я попытался создать 2 класса, в которых один будет содержать другой.
Файл 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
Файл 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);
}
Файл B.h
:
#ifndef _B_h
#define _B_h
class B{
public:
B();
};
#endif
Файл B.cpp
:
#include "B.h"
#include <cstdio>
B::B(){
printf("this is hello from B\n");
}
Сначала я компилирую класс B, а затем класс A, но затем я получаю сообщение об ошибке:
A.h: 9: ошибка: 'B не называет тип
Как исправить эту проблему?
Ответы
Ответ 1
Препроцессор вставляет содержимое файлов A.h
и B.h
в точности, где выполняется оператор include
(это действительно просто копирование/вставка). Когда компилятор затем анализирует A.cpp
, он находит объявление класса A
, прежде чем он узнает о классе B
. Это вызывает ошибку, которую вы видите. Существует два способа решить эту проблему:
- Включить
B.h
в A.h
. Как правило, рекомендуется включать заголовочные файлы в файлы, где они необходимы. Если вы полагаетесь на косвенное включение, хотя другой заголовок или специальный порядок включения в блок компиляции (cpp файл), это только смутит вас и других, поскольку проект станет больше.
-
Если вы используете переменную-член типа B
в классе A
, компилятор должен знать точное и полное объявление B
, поскольку ему необходимо создать макет памяти для A
, Если, с другой стороны, вы использовали указатель или ссылку на B
, тогда было бы достаточно прямого объявления, потому что память, которую компилятор должен зарезервировать для указателя или ссылки, не зависит от определения класса. Это будет выглядеть так:
class B; // forward declaration
class A {
public:
A(int id);
private:
int _id;
B & _b;
};
Это очень полезно, чтобы избежать круговых зависимостей между заголовками.
Надеюсь, это поможет.
Ответ 2
Вы должны сначала включить B.h
из A.h
. B b
; не имеет смысла, пока вы не включили B.h
.
Ответ 3
Включить "B.h" в "A.h". Это приводит к объявлению "B" для компилятора при компиляции "A".
Первая пуля выполняется в случае OP.
$3.4.1/7 -
"Имя, используемое в определении класс X вне функции-члена определение тела или вложенного класса27) должны быть объявлены в одном из следующими способами:
- до его использования в класс X или быть членом базового класса из X (10.2), или
- если X является вложенным класс класса Y (9.7), перед определение X в Y или должно быть член базового класса Y (это поиск применяется в свою очередь к Ys охватывающих классы, начиная с самый внутренний охватывающий класс), 28) или
- если X является локальным классом (9.8) или является вложенный класс локального класса, до определение класса X в блоке включая определение класса X, или
- если X является членом пространства имен N, или является вложенным классом класса, который является членом N или является локальным классом или вложенный класс внутри локального класса функции, являющейся членом N, до определения класса X в пространство имен N или в одном из Ns, охватывающих Пространства имен".
Ответ 4
Проблема заключается в том, что вам нужно включить B.h
в ваш файл A.h
. Проблема в том, что в определении A
компилятор все еще не знает, что такое B
. Вы должны включить все определения всех типов, которые вы используете.
Ответ 5
error 'Class' does not name a type
На всякий случай кто-то делает ту же самую идиотскую вещь, что и я...
Я создавал небольшую тестовую программу с нуля, и я набрал Класс вместо класса (с небольшим C). Я не обращал внимания на кавычки в сообщении об ошибке и слишком долго не понимал проблемы.
Мой поиск решения привел меня сюда, поэтому я думаю, что то же самое может случиться с кем-то другим.
Ответ 6
когда вы определяете класс A, в A.h, вы явно говорите, что класс имеет член B.
Вы ДОЛЖНЫ включать "B.h" в "A.h"
Ответ 7
Не пропускаете ли #include "B.h" в A.h?