могут ли два класса видеть друг друга, используя C ++?
-
11-09-2019 - |
Вопрос
Итак, у меня есть класс A, где я хочу вызвать некоторые функции класса B.Поэтому я включаю "b.h".Но в классе B я хочу вызвать функцию класса A.Если я включу "a.h", это приведет к бесконечному циклу, верно?Что я могу с этим поделать?
Решение
Каждый класс (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
это имя класса:который он может получить из прямого объявления, вместо того, чтобы включать заголовочный файл в другой заголовочный файл.
Другие советы
Помещайте только объявления функций-членов в заголовочные файлы (.h) и определения функций-членов в файлы реализации (.cpp).Тогда вашим заголовочным файлам не нужно включать друг друга, и вы можете включить оба заголовка в любой файл реализации.
В случаях, когда вам также нужно ссылаться на другой класс в подписях членов, вы можете использовать прямое объявление:
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
}
Вы также можете использовать предварительные заявления чтобы обойти эту проблему.
Попробуйте положить #ifndef
, #define
и #endif
вокруг ваших файлов .h.