Ошибка C ++ LNK2005 при добавлении нового файла заголовка

Я работаю над школьным проектом. Я знаю о своей циклической зависимости (и ранее прочитал большинство резолюций по этому поводу), но в настоящее время она работает так, как мне нужно. К сожалению, я почти уверен, что это также причина моих бед. Я хотел бы включить concol.h, чтобы его можно было использовать с обоими файлами (я хотел бы добавить цвет к моему выводу - это не требование для моего назначения, а то, что я хотел бы сделать). Я пробовал разместить этот файл заголовка в нескольких разных местах и ​​всегда получаю одни и те же ошибки. Я рассматривал возможность использования прямого объявления, как и для работы с циклической зависимостью, но не думаю, что это будет работать с пространством имен.

Ошибки:

1>Flight.obj : error LNK2005: "void * eku::std_con_out" (?std_con_out@eku@@3PAXA) already defined in BoardingPass.obj 1>Flight.obj : error LNK2005: "bool eku::colorprotect" (?colorprotect@eku@@3_NA) already defined in BoardingPass.obj 1>Flight.obj : error LNK2005: "enum eku::concol eku::textcol" (?textcol@eku@@3W4concol@1@A) already defined in BoardingPass.obj 1>Flight.obj : error LNK2005: "enum eku::concol eku::backcol" (?backcol@eku@@3W4concol@1@A) already defined in BoardingPass.obj 1>Flight.obj : error LNK2005: "enum eku::concol eku::deftextcol" (?deftextcol@eku@@3W4concol@1@A) already defined in BoardingPass.obj 1>Flight.obj : error LNK2005: "enum eku::concol eku::defbackcol" (?defbackcol@eku@@3W4concol@1@A) already defined in BoardingPass.obj 1>Source.obj : error LNK2005: "void * eku::std_con_out" (?std_con_out@eku@@3PAXA) already defined in BoardingPass.obj 1>Source.obj : error LNK2005: "bool eku::colorprotect" (?colorprotect@eku@@3_NA) already defined in BoardingPass.obj 1>Source.obj : error LNK2005: "enum eku::concol eku::textcol" (?textcol@eku@@3W4concol@1@A) already defined in BoardingPass.obj 1>Source.obj : error LNK2005: "enum eku::concol eku::backcol" (?backcol@eku@@3W4concol@1@A) already defined in BoardingPass.obj 1>Source.obj : error LNK2005: "enum eku::concol eku::deftextcol" (?deftextcol@eku@@3W4concol@1@A) already defined in BoardingPass.obj 1>Source.obj : error LNK2005: "enum eku::concol eku::defbackcol" (?defbackcol@eku@@3W4concol@1@A) already defined in BoardingPass.obj 1>D:\School Stuff\Fall 2015\CIST 2362 C++ II\Final - Airline Reservation System\Debug\Final - Airline Reservation System.exe : fatal error LNK1169: one or more multiply defined symbols found

Source.cpp

#include <fstream>
#include <iostream>
#include <iomanip>
#include "FlightComparators.h" //includes Flight.h
#include "LocationComparators.h"

//prototypes
//methods

Flight.h

#ifndef FLIGHT_H
#define FLIGHT_H

#ifndef BOARDINGPASS_H
#include "BoardingPass.h"
#endif

#include <algorithm>
#include <string>
#include <vector>
#include "Location.h"
#include "Validate.h"
#include "AirlineTypeA.h"
#include "AirlineTypeB.h"

class BoardingPass;

class Flight{
private:
    Location *departureLoc;
    Location *destinationLoc;
    char departureTime[6];
    char arrivalTime[6];
    int number;
    int freqFlyerMiles;
    int curOccupancy = 0;
    Airline *plane;
    vector<BoardingPass*> passengers;

public:
    //constructor
    Flight(Location*, Location*, string, string, int, int, char type);

    //getters
    Location* getDepartureLoc(){ return departureLoc; }
    Location* getDestinationLoc(){ return destinationLoc; }
    int getFlightNumber(){ return number; }
    int getFreqFlyerMiles(){ return freqFlyerMiles; }
    string getDepTime(){ return departureTime; }
    string getAriTime(){ return arrivalTime; }
    int getCurOccupancy(){ return curOccupancy; }
    Airline* getPlane(){ return plane; }
    vector<BoardingPass*> getPassengerList(){ return passengers; }
    bool getIsFull(){ return this->plane->getMaxPass() > curOccupancy; }

    void addPass(string, string, string);
    void cancelReservation(int);
    void displayPassengers();
    void sortPassengers();
};
#endif

BoardingPass.h

#ifndef BOARDINGPASS_H
#define BOARDINGPASS_H

#ifndef FLIGHT_H
#include "Flight.h"
#endif

#include <fstream>
#include <iostream>
#include <iomanip>
#include <string>

using namespace std;

class Flight;

class BoardingPass{

private:
    string fName;
    string lName;
    Flight* flight;
    string seat;

public:
    BoardingPass(string, string, Flight *flt, string seat);

    string getFName(){ return fName; }
    string getLName(){ return lName; }
    string getSeat(){ return seat; }
    void displayBoardingPass();
    void writeBoardingPass(fstream&);

};
#endif

concol.h

#ifndef INC_EKU_IO_CONCOL
#define INC_EKU_IO_CONCOL

/*Header file to color text and background in windows console applications
Global variables - textcol,backcol,deftextcol,defbackcol,colorprotect*/

#include<windows.h>
#include<iosfwd>

namespace eku
{

#ifndef CONCOL
#define CONCOL
    enum concol
    {
        black = 0,
        dark_blue = 1,
        dark_green = 2,
        dark_aqua, dark_cyan = 3,
        dark_red = 4,
        dark_purple = 5, dark_pink = 5, dark_magenta = 5,
        dark_yellow = 6,
        dark_white = 7,
        gray = 8,
        blue = 9,
        green = 10,
        aqua = 11, cyan = 11,
        red = 12,
        purple = 13, pink = 13, magenta = 13,
        yellow = 14,
        white = 15
    };
#endif //CONCOL

    HANDLE std_con_out;
    //Standard Output Handle
    bool colorprotect = false;
    //If colorprotect is true, background and text colors will never be the same
    concol textcol, backcol, deftextcol, defbackcol;
    /*textcol - current text color
    backcol - current back color
    deftextcol - original text color
    defbackcol - original back color*/

    inline void update_colors()
    {
        CONSOLE_SCREEN_BUFFER_INFO csbi;
        GetConsoleScreenBufferInfo(std_con_out, &csbi);
        textcol = concol(csbi.wAttributes & 15);
        backcol = concol((csbi.wAttributes & 0xf0) >> 4);
    }

    inline void setcolor(concol textcolor, concol backcolor)
    {
        if (colorprotect && textcolor == backcolor)return;
        textcol = textcolor; backcol = backcolor;
        unsigned short wAttributes = ((unsigned int)backcol << 4) | (unsigned int)textcol;
        SetConsoleTextAttribute(std_con_out, wAttributes);
    }

    inline void settextcolor(concol textcolor)
    {
        if (colorprotect && textcolor == backcol)return;
        textcol = textcolor;
        unsigned short wAttributes = ((unsigned int)backcol << 4) | (unsigned int)textcol;
        SetConsoleTextAttribute(std_con_out, wAttributes);
    }

    inline void setbackcolor(concol backcolor)
    {
        if (colorprotect && textcol == backcolor)return;
        backcol = backcolor;
        unsigned short wAttributes = ((unsigned int)backcol << 4) | (unsigned int)textcol;
        SetConsoleTextAttribute(std_con_out, wAttributes);
    }

    inline void concolinit()
    {
        std_con_out = GetStdHandle(STD_OUTPUT_HANDLE);
        update_colors();
        deftextcol = textcol; defbackcol = backcol;
    }

    template<class elem, class traits>
    inline std::basic_ostream<elem, traits>& operator<<(std::basic_ostream<elem, traits>& os, concol col)
    {
        os.flush(); settextcolor(col); return os;
    }

    template<class elem, class traits>
    inline std::basic_istream<elem, traits>& operator>>(std::basic_istream<elem, traits>& is, concol col)
    {
        std::basic_ostream<elem, traits>* p = is.tie();
        if (p != NULL)p->flush();
        settextcolor(col);
        return is;
    }

}   //end of namespace eku

#endif  //INC_EKU_IO_CONCOL 

person Aly    schedule 21.11.2015    source источник
comment
Возможный дубликат ошибки LNK2005: новое и уже удаленное определено в LIBCMTD.lib (new.obj)   -  person Ken White    schedule 21.11.2015
comment
@KenWhite, возможно, для вас это дубликат, но лично я недостаточно далеко, чтобы даже понять, что там происходит с dll и статическими библиотеками.   -  person Aly    schedule 21.11.2015


Ответы (2)


В concol.h вы определяете переменные внутри пространства имен, а не объявляете их. Переменные необходимо externed

extern HANDLE std_con_out;

в заголовке (для их определения), затем объявлен (без extern) в файле .cpp (concol.cpp).

person 1201ProgramAlarm    schedule 21.11.2015
comment
ну в этом есть смысл. Я попробую это. файл concol.h был написан не мной, а был получен с cplusplus.com/articles/Eyhv0pDG - к сожалению .. нет возможности оставлять там вопросы или комментарии к статье. - person Aly; 21.11.2015

Символы, указанные компоновщиком как «уже определенные», являются элементами, которые объявлены в файлах заголовков, но не входят в какой-либо класс. (В «области действия файла».) В результате каждый файл .cpp, который включает эти файлы заголовков, пытается переопределить для них хранилище. Когда компоновщик пытается связать объектные файлы вместе, он видит эти множественные определения и жалуется на них.

Лучшее, что можно сделать для решения вашей проблемы, - это сделать все эти элементы «статическими членами данных» класса. Это означает объявление их внутри класса и пометку их как static.

Если вы не хотите перемещать их внутри класса, вы должны позаботиться о том, чтобы они были объявлены как "extern" при включении во все файлы .cpp, кроме одного. Таким образом, только один файл .cpp попытается определить для них хранилище, и компоновщик будет счастлив.

Обычно это делается следующим образом:

a.cpp:

#define DECLARE_STORAGE
#include "myheader.h"

b.cpp, c.cpp и т. д.:

#include "myheader.h"  //without defining DECLARE_STORAGE

myheader.h

#ifdef DECLARE_STORAGE
#define POSSIBLY_EXTERN
#else
#define POSSIBLY_EXTERN extern
#endif

POSSIBLY_EXTERN int my_integer;

это заставит a.cpp скомпилировать инструкцию

int my_integer;

в то время как b.cpp, c.cpp и т. д. будут компилировать инструкцию

extern int my_integer;
person Mike Nakis    schedule 21.11.2015
comment
Я пробовал использовать этот метод, но VS продолжает отмечать #define POSSIBLY_EXTERN extern как неактивный блок препроцессора - person Aly; 21.11.2015
comment
Вы устранили ошибки? Как? В чем была проблема? - person Mike Nakis; 01.12.2015
comment
Мне не удалось устранить ошибку, поэтому я отказался от использования цвета в этом проекте. Я не мог определить причину или исправить отключенные блоки препроцессора. Из того, что я читал, это происходит, когда определено, что блок никогда не будет использоваться, но для этого не было причин. - person Aly; 01.12.2015
comment
Да, я тоже исследовал это, и это то, что я обнаружил, на что у меня не было ответа, поэтому я оставил все как есть. Но некоторые люди предлагают проигнорировать это предупреждение и продолжить. Вы пытались игнорировать это? - person Mike Nakis; 01.12.2015
comment
Да, конечно. Но поскольку он игнорировал блок, я все еще получал те же ошибки. - person Aly; 01.12.2015