2010-01-27 5 views
8

Скажем, у меня есть класс Foo с объектом класса бар в качестве членаКаков наилучший способ работы с со-зависимыми классами в C++?

class foo 
{ 
    bar m_bar; 
}; 

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

class bar 
{ 
    foo * m_pfoo; 
} 

Два класса ссылаются друг на друга и без прямого объявления, не будет компилироваться. Таким образом, добавив следующую строку, прежде чем декларация Foo в решает эту проблему

class bar; 

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

ответ

23

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

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

// foo.h 
class bar; 

class foo { 
    bar * m_pbar; 
} 

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

Это позволит вам работать - вы просто не можете поставить определения, которые требуют информации члена в ваше header - переместите его в файл .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 
} 
+0

Это кажется лучшим вариантом для того, что мне нужно. –

+1

теперь как это решение работает, если ваши созависимые классы шаблонизированы и поэтому не могут быть разделены на файлы заголовков и cpp? –

0

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

2

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

например:

class FooInterface 
{ 
    // methods here 
} 

class BarInterface 
{ 
    // methods here 
} 

class Foo : public FooInterface 
{ 
    BarInterface *pBar; 
} 

class Bar : public BarInterface 
{ 
    FooInterface *pFoo; 
} 

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

1

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

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

Смежные вопросы