Торт не может быть и есть.Либо вы используете встраивание столько, сколько можете, либо ограничиваете видимость настолько, насколько можете.С классами вы должны соблюдать баланс между использованием деривации и / или прямых членов данных, которые требуют наличия соответствующего определения класса, или косвенных членов данных, то есть указателей или ссылок, которые требуют только объявления класса.Ваш подход предпочитает встраивание / прямое включение, противоположная крайность будет:
foo.h
#ifndef FOO_H
#define FOO_H
typedef int foo_t;
int foo();
class foo_c {};
#endif /* FOO_H */
bar.h
#ifndef BAR_H
#define BAR_H
typedef foo_t bar_t;
int bar();
class foo_c;
class bar_c {
public:
bar_c();
private:
foo_c * my_foo_c;
};
#endif /* BAR_H */
zoo.h
#ifndef ZOO_H
#define ZOO_H
typedef bar_t zoo_t;
int zoo();
class zoo_c {
public:
zoo_c();
private:
bar_c * my_bar_c;
};
#endif /* ZOO_H */
foo.c
#include "foo.h"
int foo() {
return 1;
}
bar.c
#include "bar.h"
#include "foo.h"
int bar() {
return foo();
}
bar_c::bar_c() : my_foo_c(new foo_c()) {}
zoo.c
#include "zoo.h"
#include "bar.h"
int zoo()
{
return bar();
}
zoo_c::zoo_c() : my_bar_c(new bar_c()) {}
В некотором роде можно ввести дополнительный уровень исходных файлов, который вы можете назвать .inl
, переместите реализации функций туда и сделайте их встроенными.Таким образом, вы можете включить эти новые файлы после оригинальных заголовков и только там, где это действительно необходимо, и получить как ограниченную видимость, так и максимальную вставку.Однако я не думаю, что это стоит затраченных усилий.
Шаблоны еще больше усложнят ситуацию, поскольку в общем случае определения должны быть доступны везде, где требуется создание экземпляра шаблона.Существуют способы контроля этого, например, путем принудительного создания экземпляров требуемых специализаций, чтобы избежать включения определений для каждой точки использования, но опять-таки добавленное усложнение может не стоить.
Если вас беспокоит время компиляцииобычно гораздо проще полагаться на механизм предварительной компиляции заголовка вашего компилятора.