views:

73

answers:

2

I have an implementation for printing out enum values in c++

If I put all the code in a .h file, everything works nicely. If I separate out the function implementation into .cpp files, I get a linker error.

Here is my main file

#include <iostream>
#include <vector>
#include "Day.h"
using namespace std;

int main(){
    initializeDayNames();
    Day a = Clubs;
    cout << a;
}

Here is the .h file

#ifndef __Day__
#define __Day__

#include <iostream>
#include <vector>
#include <string>
using namespace std;

enum Day {Clubs, Hearts, Diamonds, Spades} ;

vector<string> DayNames = vector<string>();

ostream & operator<<(ostream & out, Day cs);

void initializeDayNames();

#endif

and the .cpp file

#include <iostream>
#include "Day.h"
#include<string>
#include<vector>
using namespace std;

void initializeDayNames(){
    DayNames.push_back("Clubs");
    DayNames.push_back("Hearts");
    DayNames.push_back("Diamonds");
    DayNames.push_back("Spades");
}


ostream & operator<<(ostream & out, Day cs){
    out << DayNames[cs];
    return out;
}

What am I doing wrong here

The specific error is

Error   1   error LNK2005: "class std::vector<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::allocator<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > > DayNames" (?DayNames@@3V?$vector@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@@std@@A) already defined in Day.obj main.obj

and

Error   2 fatal error LNK1169: one or more multiply defined symbols found   
+5  A: 

You are initializing two copies of

vector<string> DayNames = vector<string>();

because you included the header twice.

You should replace it with

extern vector<string> DayNames;

in the h file and

vector<string> DayNames = vector<string>();

in the cpp file.

Also you seem to have two copies of

ostream & operator<<(ostream & out, Day cs);

The reason your header guards isn't helping this case is that when you include the headers, you basically duplicate the definitions in all your files that you have included the header.

In C, when you declare a variable, you basically instantiate it/allocate static space for it. When you put the variable declaration in the header, what you are effectively doing is allocating static storage space for the variable in two different objects, giving you your error.

Xzhsh
Fixed the ostream duplication part.
TP
Is there still a problem with compiling? I haven't put it into a compiler so I'm not really sure if that's all the problems there :)
Xzhsh
Shouldnt the #ifndef declarations protect against stuff in the header from being declared twice??
TP
it works with the extern stuff, but im kinda confused as to why the #ifndef part isnt helping wit it being included twice
TP
Nope, the ifndef is to prevent stuff in the header being declared twice in the same file, but what happens is that when you include a header in two different files, the contents are duplicated (which is why you should generally only write function headers and stuff in .h files).
Xzhsh
Also, it's a matter of preference, but many people would say to avoid double underscores in your code, because they are sometimes system reserved.Edited answer.
Xzhsh
Greg Domjan
A: 

You're missing extern on the DayNames declaration.

kprobst