Подтвердить что ты не робот

Имя класса не называет тип в С++

Я только начал программировать на С++, и я попытался создать 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 не называет тип

Как исправить эту проблему?

4b9b3361

Ответ 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?