Многократное включение в несколько файлов - PullRequest
1 голос
/ 24 февраля 2011

Я делаю небольшую игру.

В BattleRecord.h:

#ifndef _CHARACTER_H_
#define _CHARACTER_H_
#include "Character.h"
#endif

class BattleRecord
{
public:
    Character Attacker;
    Character Defender;
    Status status;
    int DamageDealt;    
    int GoldEarned;
    int ExpGained;
};

In Character.h:

#ifndef _EQUIPMENT_H_
#define _EQUIPMENT_H_
#include "Equipment.h"
#endif

class BattleRecord;
class Character
{
BattleRecord AttackEnemy(Character &Enemy);
}

В BattleRecord.h:

#ifndef _CHARACTER_H_
#define _CHARACTEr_H_
#include "Character.h"
#endif

#ifndef _BATLE_RECORD_H_
#define _BATLE_RECORD_H_
#include "BattleRecord.h"
#endif

class GUI
{
public:
//GUI Methods, and two of these:
void ViewStats(Character &Player);
void Report(BattleRecord Record)
}

Проблема здесь в том, что мои Character.h и BattleRecord.h должны включать друг друга, и это определенно вызовет многократную проблему переопределения. Поэтому я использовал предварительное объявление в Character.h, добавив:

class BattleRecord;

Проблема решена. Но для того, чтобы сообщить о битве, GUI.h снова нужен BattleRecord.h, поэтому я должен включить BattleRecord.h в GUI.h. Я также должен включить Character.h для перехода в функцию ViewStat. Я получил ошибку и застрял с этим до этого пионта.

Ответы [ 5 ]

11 голосов
/ 24 февраля 2011

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

Например, в BattleRecord.h

#ifndef _BATTLE_H_
#define _BATTLE_H_
#include "Character.h"

class BattleRecord
{
public:
    Character Attacker;
    Character Defender;
    Status status;
    int DamageDealt;    
    int GoldEarned;
     int ExpGained;
};

#endif // _BATTLE_H_
3 голосов
/ 24 февраля 2011

Поместите #endif в конец файла, а не в конец списка включений, или используйте #pragma once вверху, если ваш компилятор поддерживает это, хотя это менее переносимо.

Edit:

Чтобы дополнительно объяснить, что делает #ifdef & ifndef, это говорит компилятору полностью включить или исключить код из компиляции.

// if _UNQIUEHEADERNAME_H_ is NOT defined include and compile this code up to #endif
#ifndef _UNQIUEHEADERNAME_H_
// preprocessor define so next time we include this file it is defined and we skip it
#define _UNQIUEHEADERNAME_H_
// put all the code classes and what not that should only be included once here
#endif // close the statement 

Причина, по которой вы хотите это сделать, заключается в том, что включение заголовочного файла в основном говорит: «поместите весь код в этот файл здесь», если вы сделали это несколько раз, у вас возникли бы конфликты имен из-за переопределения объектов и медленная компиляция лучший сценарий.

1 голос
/ 24 февраля 2011

В общем, используйте предварительную декларацию вместо include. Это минимизирует количество включений, которые вы включаете в файл. Единственное исключение - когда определяемый вами класс является производным, тогда вам нужно включить базовый класс.

0 голосов
/ 24 февраля 2011

ОК, все

Спасибо, что помогли мне. Я переписал все включения для заголовочных файлов, как это было предложено, и теперь он работает безупречно. Потратьте немного времени на то, чтобы сделать это неправильно во многих уроках.

0 голосов
/ 24 февраля 2011

В дополнение к упомянутым выше проблемам включения защиты (у вас также есть несовпадение _CHARACTEr_H _ / _ CHARACTER_H_, которое может вызвать проблемы во второй строке GUI.h), вы можете захотеть пересмотреть дизайн объекта, чтобы Персонаж не атаковал(), но есть класс Battle (), на который ссылаются два персонажа и после битвы создается BattleRecord.Это предотвратило бы когда-либо, чтобы класс Character узнавал о BattleRecords в первую очередь, допускал бы возможность многосимвольных сражений в будущем, многоуровневых сражений или специальных сражений посредством наследования класса Battle.

...