Ошибка нескольких символов C++

Я думал ifndef something #define something body #endif решил эту ошибку, поэтому я не уверен, почему это происходит.

//Library.h
#ifndef __LIBRARY__
#define __LIBRARY__

#include <iostream>
#include <string>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <cstdarg>
#include <vector>
#include <ctime>
#include <cmath>
#include <cstdlib>

//file includes
#include "Globals.h"

using namespace std;

#endif //__LIBRARY__

-

//globals.h
//global variables
#ifndef __GLOBAL__
#define __GLOBAL__

#include <vector>
#include <iostream>
#include <string>

//prototypes
bool Poglathon(std::vector<std::string>& text);
void NPCTalk(std::string const& speaker,std::vector<std::string> const& text);
void wait(double seconds);

//player stats
std::string name;
double str;     //strength
double wis;     //wisdom
double ref;     //reflex
double hp;      //health points
double i;       //initiative
double inte;    //intelligence
double c;       //courage
int gold;       //gold
int xp;         //experience
int ap;         //armour points
int wd;         //weapon damage
int lvl;        //level
int sp;         //skill points

#endif //__GLOBAL__

Тогда есть два других файла cpp, которые включают "Library.h".

2 ответа

Решение

Проблема в том, что в вашем заголовочном файле globals.h вы объявляете набор переменных, которые по умолчанию имеют внешнюю связь, а именно, все глобальные переменные!

Когда вы создаете прототип функции в заголовочном файле, вы объявляете функцию, но не определяете ее. Совершенно законно иметь несколько объявлений одной и той же функции, поэтому, если несколько разных файлов все #include тот же заголовок и объявить ту же функцию, это прекрасно. С другой стороны, если у вас есть глобальные переменные в заголовочном файле, вы определяете эти переменные. Переменные могут быть определены только один раз в C++ (это называется правилом с одним определением), и если несколько файлов определяют одну и ту же переменную или функцию, это вызовет ошибку компоновщика, поскольку компоновщик не будет знать, какую версию использовать. Это причина, кстати, что вы не #include Файлы.cpp, так как если бы вы это сделали, вы умножили бы все функции, экспортируемые этим заголовком.

Чтобы решить эту проблему, в заголовке вы захотите изменить определения этих переменных на объявления переменных, используя extern ключевое слово:

//player stats
extern std::string name;
extern double str;     //strength
extern double wis;     //wisdom
extern double ref;     //reflex
extern double hp;      //health points
extern double i;       //initiative
extern double inte;    //intelligence
extern double c;       //courage
extern int gold;       //gold
extern int xp;         //experience
extern     extern int ap;         //armour points
extern int wd;         //weapon damage
extern int lvl;        //level
extern int sp;         //skill points

Это позволит любое количество файлов #include этот заголовок, поскольку ни один из них фактически не определяет переменные; они просто заявляют, что переменные будут где-то существовать. Затем вы должны создать новый файл.cpp, вероятно, globals.cpp, который фактически определяет переменные:

#include "globals.h"

std::string name;
double str;     //strength
double wis;     //wisdom
double ref;     //reflex
double hp;      //health points
double i;       //initiative
double inte;    //intelligence
double c;       //courage
int gold;       //gold
int xp;         //experience
int ap;         //armour points
int wd;         //weapon damage
int lvl;        //level
int sp;         //skill points

Это фактические определения переменных, и, поскольку они существуют только в одном месте (globals.cpp), вы больше не получите ошибок компоновщика.

Надеюсь это поможет!

Есть много проблем с вашим кодом C++

  • Никогда не объявляйте глобальные переменные непосредственно в заголовке, который вызывает несколько символов, так как они будут появляться в каждом модуле компиляции (файл ~cpp использует их). Одним из решений было бы сделать их внешними, но я призываю вас использовать класс или структуру удерживая эти параметры вместо.

Кроме того:

  • Никогда не делайте "использование пространства имен xxx" внутри заголовочных файлов в глобальной области видимости. Вы заставите всех, кто использует заголовок, тянуть символы в глобальном пространстве имен.
  • Это не следование семантике C++, больше похоже на C (я бы действительно обернул всю статистику игрока внутри класса с тем же именем!)
Другие вопросы по тегам