2015-07-03 3 views
2

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

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

Unit.hpp:

#ifndef PROJECT_UNIT_HPP 
#define PROJECT_UNIT_HPP 

#include "GridNode.hpp" 

class Unit 
{ 
private: 
    /* Fields */ 
    int xPos, yPos, ownerID; 
    std::vector<GridNode> influenceMap; 

public: 
    /* Constructors */ 
    Unit(int x, int y, int id) : xPos(x), yPos(y), ownerID(id) 
    { 
     influenceMap.push_back(GridNode()); 
    } 

    /* Methods */ 
    std::vector<GridNode> getMap() {return influenceMap;} 
}; 

#endif 

GridNode.hpp:

#ifndef PROJECT_GRIDNODE_HPP 
#define PROJECT_GRIDNODE_HPP 

#include "Unit.hpp" 

class GridNode 
{ 
private: 
    /* Members */ 
    int id; 
    std::vector<Unit> nodeUnits; 

public: 
    /* Static vars */ 
    static int nodeLength; 

    /* Constructors */ 
    GridNode() 
    { 
     std::cout << "Reached here!\n"; 
    } 
}; 

#endif 
+1

это может оказаться весьма полезным для первой работы, как это сделать, когда положить оба класса в один * * заголовочный файл. – Hurkyl

+0

Не мог бы я решить ту же проблему? Если бы я сделал прямое объявление GridNode, затем определил Unit, а затем полностью определил GridNode, я бы получил еще одну ошибку неполного типа, когда я пытаюсь вызвать какой-либо конструктор GridNode, не так ли? – rawa

+0

Да, все равно будут проблемы, но с раздельными заголовками, особенно с круговыми включениями, вводится еще больше осложнений; разработка, как исправить это, будет проще, если вы решите каждый набор проблем самостоятельно. – Hurkyl

ответ

1

Вы должны вперед декларации и двигаться на функции-члены органов (в том числе конструкторов и деструкторов) из тела класса, и после того, как включение определения другого класса.

Даже неявные конструкторы и деструкторы будут ломать вещи, вы должны будете явная предоставленным пользователем декларации (хотя вы можете использовать определения компилятора, предоставляемые через = default)

class GridNode; 
class Unit 
{ 
private: 
    /* Fields */ 
    int xPos, yPos, ownerID; 
    std::vector<GridNode> influenceMap; 

public: 
    /* Constructors */ 
    Unit(int x, int y, int id); 
    Unit(const Unit&); 
    ~Unit(); 

    /* Methods */ 
    std::vector<GridNode> getMap(); 
}; 

#include "GridNode.hpp" 

inline Unit::Unit(int x, int y, int id) : xPos(x), yPos(y), ownerID(id) 
{ 
    influenceMap.push_back(GridNode()); 
} 

inline Unit::Unit(const Unit&) = default; 

inline Unit::~Unit() = default; 

inline std::vector<GridNode> Unit::getMap() {return influenceMap;} 
+0

Просто для ясности, ваш предоставленный код все в одном файле? Если это так, я предполагаю, что все это в файле Unit.hpp, правильно? Или это файл Unit.hpp и файл Unit.cpp? Оператор include в середине кода блокирует меня, так как я никогда не видел его в середине кода. – rawa

+0

@awar: Это замена вашего содержимого 'Unit.hpp', проходящего между строками' # ifndef'/'# define' /' # endif'. Все здесь уже найдено в 'Unit.hpp' в вашем вопросе, я только что изменил порядок. –

+0

Большое спасибо, последний вопрос: почему ваш конструктор по умолчанию принимает объект Unit в качестве параметра? Разве он не должен принимать никаких параметров? – rawa

2

Все, что вам нужно сделать, это #include <vector> в как и вперед объявить class Unit; в GridNode.hpp:

#ifndef PROJECT_GRIDNODE_HPP 
#define PROJECT_GRIDNODE_HPP 

// using std::vector 
#include <vector> 

// Forward declare 
class Unit; 

class GridNode 
{ 
private: 
    /* Members */ 
    int id; 
    std::vector<Unit> nodeUnits; 

public: 
    /* Static vars */ 
    static int nodeLength; 

    /* Constructors */ 
    GridNode() 
    { 
     std::cout << "Reached here!\n"; 
    } 
}; 

#endif 
+0

Неявно объявленный '~ GridNode()' destructor не сможет скомпилироваться правильно, так как ему нужно создать экземпляр 'std :: vector :: ~ vector()', который, в свою очередь, нуждается в полном определении 'Unit' –

+0

@BenVoigt. * definition * требуется 'vector :: ~ vector()', и деструктор будет определяться неявно при использовании (т. е. вызванном). – Potatoswatter