Файлы (*.h
или *.cpp
) должны содержать только те файлы, от которых они напрямую зависят.
Файлы не должны содержать файлы, от которых они не зависят.
Один способ Разорвать циклические зависимости - поместить реализацию в исходный файл foo.cpp
вместо встроенного в заголовочный файл foo.h
.
Один из способов разорвать зависимости от глобальных переменных - вместо этого передать их как параметры вместо жестко запрограммировав их в подпрограммах.
Использование предварительного объявления можно использовать, чтобы избежать включения заголовочного файла, который используется только для объявления типа. Только когда детали типа, такие как его методы и площадь, не важны. Увы, предварительные объявления для шаблонных классов сложнее.
Для файлов в примере OP приведена альтернативная реализация, включающая эти предложения.
fruit.h
#ifndef FRUIT_H
#define FRUIT_H
class Map;
class Fruit {
public:
int pos = 1;
auto draw(Map const&) -> int;
};
#endif
map.h
#ifndef MAP_H
#define MAP_H
class Map {
public:
int size = 20;
};
#endif
stone.h
#ifndef STONE_H
#define STONE_H
class Fruit;
class Map;
class Stone {
public:
auto draw(Map const& map, Fruit const& fruit) -> int;
};
#endif
фрукт. cpp
// Identity.
#include "fruit.h"
// Other dependencies.
#include "map.h"
auto Fruit::draw(Map const& map) -> int {
return map.size;
}
камень. cpp
// Identity.
#include "stone.h"
// Other dependencies.
#include "fruit.h"
#include "map.h"
auto Stone::draw(Map const& map, Fruit const& fruit) -> int {
return map.size * fruit.pos;
}
основной. cpp
#include <iostream>
#include "fruit.h"
#include "map.h"
#include "stone.h"
using std::cout;
int main() {
auto map = Map{};
auto fruit = Fruit{};
auto stone = Stone{};
map.size = 17;
fruit.pos = 3;
cout << "map.size is " << map.size << "\n";
cout << "fruit.pos is " << fruit.pos << "\n";
cout << "fruit.draw(map) is " << fruit.draw(map) << "\n";
cout << "stone.draw(map, fruit) is " << stone.draw(map, fruit) << "\n";
}