два класса могут видеть друг друга с помощью C ++? - PullRequest
21 голосов
/ 03 декабря 2009

Итак, у меня есть класс A, где я хочу вызвать некоторые функции класса B. Поэтому я включаю "б.ч". Но в классе B я хочу вызвать функцию класса A. Если я добавлю «a.h», он окажется в бесконечном цикле, верно? Что я могу с этим поделать?

Ответы [ 4 ]

37 голосов
/ 03 декабря 2009

Поместите только объявления функций-членов в файлы заголовков (.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
}
28 голосов
/ 03 декабря 2009

Каждый класс (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 - это имя класса: которое он может получить из прямого объявления, вместо включения заголовочного файла в другой заголовочный файл.

10 голосов
/ 03 декабря 2009

Вы также можете использовать предварительные объявления , чтобы обойти проблему.

0 голосов
/ 20 апреля 2010

Попробуйте поместить #ifndef, #define и #endif вокруг ваших файлов .h.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...