C ++: как два класса могут вызывать друг друга без переопределения и без заголовков, вызывающих друг друга - PullRequest
2 голосов
/ 28 января 2010

У меня есть небольшая проблема с этим. У меня есть класс A, который создает экземпляр объекта B, а затем B, который создает экземпляр объекта A. Это вообще возможно? Я попытался добавить это в заголовках каждого

#ifndef A
#define A
  class a...
#endif

но если держать меня в бесконечном цикле заголовка, который включает в себя максимальный заголовок, то очевидно, что один вызывает другой, а другой - тот. Есть ли способ добиться этого?

edit: Хорошо, это кажется хорошим ответом, но теперь A жалуется, что у B нет Конструктора, несмотря на тот факт, что он определенно имеет конструктор. Я не могу понять это.

Ответы [ 6 ]

9 голосов
/ 28 января 2010

Вы можете заранее объявить классы, например:

A.h * * 1004

class B;

class A
{
    B* a_;
};

B.h

class A;

class B
{
    A* a_;
};

В ваших исходных файлах, где вы фактически используете классы (то есть создаете их, уничтожаете их, используете их члены и т. Д.), Вам нужно будет включить оба заголовка, чтобы их определения были доступны:

#include "A.h"
#include "B.h"
4 голосов
/ 28 января 2010

Вы должны сломать эту круговую зависимость. Например, вы могли бы использовать указатель на B, и затем вы могли бы затем объявить класс B вперед.

2 голосов
/ 28 января 2010

Вы можете отправить объявление A в заголовочный файл B, и наоборот, чтобы достичь того, что вы хотите.

// In B.h
class A;

class B
{
  private:
    A a;
};

См. Википедия для получения дополнительной информации.

2 голосов
/ 28 января 2010

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

В файле classA.h удалите все включения в classB.h и переместите их в classA.cpp. Затем перед объявлением classA напишите строку class B; для прямого объявления класса B. Таким образом, вы можете иметь переменные-члены B * (но не B) внутри класса A. Затем сделайте то же самое для classB.

2 голосов
/ 28 января 2010

Вы пробовали использовать предварительную декларацию?

class B;

class A
{
  private:
     B* instanceOfB_;

};
1 голос
/ 28 января 2010

Если вы имеете в виду class A {B b;}; и class B {A a;}, нет, вы не можете. Члены класса данных включены в класс, так что у вас будет B, который включает A, который включает B, который включает A .... Помните, в C ++ объект данных не является ссылкой на что-то, но является фактическим вещь.

Вам нужно что-то вроде class A {B * b;}; и class B {A * a;}, где вы предоставляете указатели. Перед определениями нужно что-то вроде class A; class B;, чтобы сообщить компилятору, что A и B являются классами. Это называется "предварительные декларации".

...