0

I am working on a project for school. I am aware of my circular dependency(And have read most of the resolutions here for that previously) but it works currently the way I need it to. Sadly I'm pretty sure it is also the cause of my woes. I would like to include concol.h so that it can be used with both files (I'd like to add some color to my output - not a requirement for my assignment but something I would like to do). I've tried placement of this header file in several different locations and I always get the same errors. I considered using the forward declaration like I did to work with the circular dependency but I don't think that will work with a namespace.

Errors:

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 
Aly
  • 57
  • 1
  • 9
  • Possible duplicate of [error LNK2005: new and delete already defined in LIBCMTD.lib(new.obj)](http://stackoverflow.com/questions/1146338/error-lnk2005-new-and-delete-already-defined-in-libcmtd-libnew-obj) – Ken White Nov 21 '15 at 03:33
  • @KenWhite maybe to you it is a duplicate but I personally am not far enough along to even understand what is happening there with dll and static libraries. – Aly Nov 21 '15 at 03:42

2 Answers2

1

In concol.h you're defining variables inside a namespace, not declaring them. The variables need to be externed

extern HANDLE std_con_out;

in the header (to define them), then declared (without the extern) in a .cpp file (concol.cpp).

1201ProgramAlarm
  • 32,384
  • 7
  • 42
  • 56
  • ah this makes sense. I will try this. the concol.h file was not written by me but was obtained from http://www.cplusplus.com/articles/Eyhv0pDG/ - sadly.. no option to leave questions or comments on the article there. – Aly Nov 21 '15 at 03:40
0

The symbols indicated by the linker as "already defined" are items that are declared in header files, but outside of any class. (In "file scope".) As a result, every .cpp file which includes these header files is trying to redefine storage for them. When the linker tries to link the object files together, it sees these multiple definitions, and it complains about them.

The best thing to do to solve your problem is to make all these items "static data members" of a class. This means declaring them within a class, and marking them as static.

If you do not want to move them inside a class, then you must see to it that they will be declared as "extern" when included by all .cpp files but one. This way, only one .cpp file will try to define storage for them, and the linker will be happy.

This is usually done as follows:

a.cpp:

#define DECLARE_STORAGE
#include "myheader.h"

b.cpp, c.cpp etc:

#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;

this will cause a.cpp to compile the statement

int my_integer;

while b.cpp, c.cpp etc. will compile the statement

extern int my_integer;
Mike Nakis
  • 56,297
  • 11
  • 110
  • 142
  • I tried using this method bu VS keeps marking `#define POSSIBLY_EXTERN extern` as an "Inactive Preprocessor Block" – Aly Nov 21 '15 at 04:03
  • Did you resolve the errors? How? What was the problem? – Mike Nakis Nov 30 '15 at 22:04
  • I was unable to resolve the error so I have currently opted out of using color on this project. I could not determine a reason or fix for the disabled preprocessor blocks. From what I've read, this happens when it is determined the block will never be used but there was no reason for that. – Aly Nov 30 '15 at 23:19
  • Yes, I researched it too, and that's what I discovered, to which I did not have an answer, so I left it at that. But some people suggest that you can ignore this warning and proceed. Did you try ignoring it? – Mike Nakis Nov 30 '15 at 23:36
  • Yes, of course. But because it was "ignoring the block" I was still getting the same errors. – Aly Dec 01 '15 at 00:23