Несколько определений в C++ (Visual Basic 2010)
Я пытаюсь попрактиковаться в написании кода в свое свободное время (объединяя ряд своих интересов, чтобы не отвлекаться) и столкнулся с странной ошибкой, на которую не могу найти ответ. У меня есть 4 файла, с которыми я работаю, два заголовочных файла, один файл определения класса и основной файл. Я совершенно уверен, что не включаю файл Dice.h более одного раза (однако именно на это указывает ошибка, и я больше не уверен, отсюда и этот вопрос). Что я тут напутал, чтобы произвести эти ошибки?
Коды ошибок
Ошибка 3, ошибка LNK1169: найден один или несколько кратно определенных символов (путь к файлу обрезан)
Ошибка 2, ошибка LNK2005: "int __cdecl dice(int,int)" (? Dice@@YAHHH@Z) уже определено в Creature.obj (путь к файлу обрезан)
Путь к файлу: c:\Users\ Имя пользователя \documents\visual studio2010\Projects\RPGTest\RPGTest\RPGTest.(Ошибка 3 ссылается на файл.exe, ошибка 2 ссылается на файл.obj).
Сам код:
Dice.h
#ifndef SET_DICE_H_
#define SET_DICE_H_
#include <iomanip>
#include <iostream>
#include <stdlib.h>
using namespace std;
int dice(int number, int sides){
int total=0, dice;
srand(time(NULL));
int results=0;
do {
dice = rand()%sides+1;
total+=dice;
number--;
} while (number > 0);
results = total;
return results;
}
#endif
Creature.h
#ifndef CREATURE_H_
#define CREATURE_H_
#include <iomanip>
#include <iostream>
#include "Dice.h"
using namespace std;
class Creature {
public:
Creature(int,int,int,int,int,int,int,int,int,int,int,int);
void set_hp();
void set_saves();
void set_ac();
void set_bab();
void set_name();
void update_hp(int);
void update_ac(int);
void update_fsave(int);
void update_rsave(int);
void update_wsave(int);
int get_ac();
int get_hp();
int get_fsave();
int get_rsave();
int get_wsave();
int get_bonus(int);
int get_bab();
string get_name();
private:
int strength, dexterity, constitution, intellegence, wisdom, charisma;
int bab, fbsave, rbsave, wbsave;
int hdnum, hdsize;
int hp, fsave, rsave, wsave, ac;
string name;
};
#endif
Creature.cpp
#include "Creature.h"
#include <math.h>
#include <iostream>
using namespace std;
Creature::Creature(int strength,int dexterity,int constitution,
int intellegence,int wisdom,int charisma,int bab,int fbsave,
int rbsave,int wbsave,int hdnum,int hdsize){
strength = strength;
dexterity = dexterity;
constitution = constitution;
intellegence = intellegence;
wisdom = wisdom;
charisma = charisma;
bab = bab;
fbsave = fbsave;
rbsave = rbsave;
wbsave = wbsave;
hdnum = hdnum;
hdsize = hdsize;
}
int Creature::get_bonus(int stat){
int bonus = floor((double(stat)-10)/2);
return bonus;
}
void Creature::set_ac(){
ac=10+get_bonus(dexterity);
}
void Creature::set_hp(){
hp = dice(hdnum,hdsize) + get_bonus(constitution)*hdnum;
}
void Creature::set_saves(){
fsave = fbsave + get_bonus(constitution);
rsave = rbsave + get_bonus(dexterity);
wsave = wbsave + get_bonus(wisdom);
}
void Creature::set_bab(){
bab = hdnum;
}
void Creature::set_name(){
cout << "Please enter a name for this creature: ";
cout << "\nSorry! I don't work yet!";
cout << "\nInstead all creatures are named Larry!\n";
name = "Larry!";
}
void Creature::update_hp(int input){
hp = hp + input;
}
void Creature::update_fsave(int input){
fsave = fsave+input;
}
void Creature::update_rsave(int input){
rsave = rsave+input;
}
void Creature::update_wsave(int input){
wsave = wsave+input;
}
void Creature::update_ac(int input){
ac = ac+input;
}
int Creature::get_ac(){
return ac;
}
int Creature::get_hp(){
return hp;
}
int Creature::get_fsave(){
return fsave;
}
int Creature::get_rsave(){
return rsave;
}
int Creature::get_wsave(){
return wsave;
}
int Creature::get_bab(){
return bab;
}
RPGTest.cpp
#include "Creature.h"
#include <math.h>
//#include "Dice.h"
#include <iostream>
#include <iomanip>
using namespace std;
int main(){
int str = dice(3,6), dex = dice(3,6), con = dice(3,6), intel = dice(3,6), wis = dice(3,6), cha = dice(3,6);
int fbs = dice(1,6), rbs = dice(1,6), wbs = dice(1,6);
int hdn = dice(1,10), hds = 8, bab = dice(1,8);
cout << "Welcome to RPG Creature Tester v0.1\n";
cout << "This .exe file is meant to test the creature class functions and definitions.\n";
cout << "This will be done by randomly generating and displaying a creature.\n";
cout << "What you don't see right now is the random generation of a creature.\n";
cout << "Once it's finished, the \'statsheet\' will be shown.\n";
cout << "Cheers!\n\n";
Creature potato (str, dex, con, intel, wis, cha, bab, fbs, rbs, wbs, hdn, hds);
potato.set_ac();
potato.set_hp();
potato.set_name();
potato.set_saves();
cout << "OUTPUT BRICK YAY\n";
cout << "Str: " << str << endl;
cout << "HP: " << potato.get_hp() << " AC: " << potato.get_ac() << " Fort/Reflex/Will Save: " << potato.get_fsave() << "/" << potato.get_rsave() << "/" << potato.get_wsave();
return 0;
}
Поскольку я в основном самоучка, я рад любым другим советам, но моя главная проблема в том, что я не уверен, почему я получаю "множественную" ошибку определения. Я провел некоторое исследование по другим вопросам с подобными сообщениями об ошибках, но я не видел ничего, что сразу бросилось бы в меня как "ответ".
Спасибо всем!
1 ответ
C++ работает, компилируя отдельные блоки перевода и затем связывая их вместе.
Это означает, что каждый исходный файл компилируется самостоятельно. Так как #include
Директива в основном вставляет весь включенный код, в вашей ситуации вы получите несколько единиц перевода, которые определяют
int dice(int number, int sides) {
...
}
Компиляция проходит нормально, но при компоновке обнаруживаются множественные определения этой функции, что приводит к ошибке.
Для решения этой проблемы у вас есть два способа:
- объявлять
int dice(int, int)
в заголовочном файле, но определить (реализовать его) в исходном файле - сохранить определение как есть, но предварять
static
к этому. Это говорит компилятору, что каждый модуль перевода получит свойdice
метод. Это решение, хотя и является заманчивым, приводит к увеличению размера двоичного файла, поскольку у вас будет несколько реализаций одного и того же метода.