Каков наилучший способ иметь дело с зависимыми классами в C ++? - PullRequest
10 голосов
/ 27 января 2010

Скажем, у меня есть класс foo с объектом класса bar в качестве члена

class foo
{
    bar m_bar;
};

Теперь предположим, что bar должен отслеживать foo, которому он принадлежит

class bar
{
    foo * m_pfoo;
}

Два класса ссылаются друг на друга и без предварительного объявления не будут компилироваться. Поэтому добавление этой строки до объявления foo решает эту проблему

class bar;

Теперь проблема в том, что при записи файлов заголовков каждый заголовок зависит от другого: для foo.h нужны определения в bar.h и наоборот. Как правильно бороться с этим?

Ответы [ 4 ]

24 голосов
/ 27 января 2010

Вам необходимо переместить все членские права доступа из заголовка в исходные файлы.

Таким образом, вы можете заранее объявить ваши классы в заголовке и определить их в foo:

// foo.h
class bar;

class foo {
    bar * m_pbar;
}

// bar.h
class foo;
class bar {
    foo * parent;
}

Это позволит вам работать - вы просто не можете поместить определения, требующие информацию об участнике, в свой заголовок - переместите его в файл .cpp. Файлы .cpp могут включать как foo.h, так и bar.h:

// Foo.cpp
#include "foo.h"
#Include "bar.h"

void foo::some_method() {
     this->m_pbar->do_something(); // Legal, now, since both headers have been included
}
2 голосов
/ 27 января 2010

Полагаю, одним из способов является создание абстрактных классов интерфейса без членов. Затем создайте подкласс foo и bar из этих классов интерфейса.

например:.

class FooInterface
{
   // methods here
}

class BarInterface
{
   // methods here
}

class Foo : public FooInterface
{
   BarInterface *pBar;
}

class Bar : public BarInterface
{
   FooInterface *pFoo;
}

Это нарушает цикл зависимостей (если сами интерфейсы не зависят друг от друга, и если это так, то их, вероятно, следует объявить в одном файле)

1 голос
/ 27 января 2010

В вашем примере foo зависит от bar (потому что он содержит фактический bar объект), но bar не зависит от foo (поскольку он содержит только foo *). Теперь bar зависит от того, является ли foo именем типа, поэтому bar.h требуется предварительное объявление имени: class foo;. foo зависит от bar, поэтому foo.h должен содержать #include "bar.h"

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

0 голосов
/ 27 января 2010

Насколько я знаю, единственный реальный способ сделать это - использовать указатели, так как они не требуют определения класса до тех пор, пока единица перевода (.cpp) в этом случае оба класса не будут определены правильно.

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