Итак, у меня есть класс A, где я хочу назвать некоторые функции класса B. Поэтому я включаю "b.h". Но, в классе B, я хочу вызвать функцию класса A. Если я включаю "a.h", он заканчивается бесконечным циклом, верно? Что я могу сделать с этим?
Могут ли два класса видеть друг друга с помощью С++?
Ответ 1
Каждый класс (A и B) должен иметь заголовочный файл и файл реализации.
Каждый заголовочный файл (например, A.h
) не должен включать другой заголовочный файл (например, B.h
), но может включать прямую ссылку на другой класс (например, оператор вроде class B;
), а затем может использовать указатели и/или ссылки на другой класс в его объявлении (например, class A
может содержать B*
как элемент данных и/или как параметр метода).
Каждый файл CPP (например, A.cpp
) может содержать более одного файла заголовка (например, A.h
и B.h
). Он рекомендовал, чтобы каждый файл CPP сначала включал свой собственный заголовочный файл (например, A.cpp
должен включать A.h
, а затем B.h
, тогда как B.cpp
должен включать B.h
, а затем A.h
).
Каждый заголовочный файл должен содержать только объявление, а не определение класса: например, он будет перечислять подписи методов класса, но не тела/реализации метода (тела/реализации метода будут находиться в .cpp
, а не в файле заголовка). Поскольку файлы заголовков не содержат сведений о реализации, они поэтому не зависят от (не нужно видеть) деталей других классов; в лучшем случае им нужно знать, что, например, B
- это имя класса, которое он может получить из прямого декларатора, вместо того, чтобы включать заголовочный файл в другой заголовочный файл.
Ответ 2
Поместите объявления только функций-членов в файлы заголовка (.h) и поместите определения функций-членов в файлы реализации (.cpp). Тогда ваши файлы заголовков не должны включать друг друга, и вы можете включить оба заголовка в файл реализации.
В случаях, когда вам нужно также ссылаться на другой класс в подписях участников, вы можете использовать декларацию forward:
class A;
Это позволяет использовать указатели и ссылочные типы (A*
и A&
), но не A
. Он также не позволяет вам называть участников.
Пример:
// a.h
struct B; // forward declaration
struct A {
void foo(B* b); // pointers and references to forward-declared classes are ok
};
// b.h
struct A; // forward declaration
struct B {
void bar(A& a); // pointers and references to forward-declared classes are ok
};
// a.cpp
#include "a.h"
#include "b.h"
void A::foo(B* b) {
b->bar(*this); // full declaration of B visible, ok to call members now
}
// b.cpp
#include "a.h"
#include "b.h"
void B::bar(A& a) {
a.foo(this); // full declaration of A visible, ok to call members now
}
Ответ 3
Вы также можете использовать передовые объявления, чтобы обойти эту проблему.
Ответ 4
Попробуйте помещать #ifndef
, #define
и #endif
вокруг ваших файлов .h.