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   
Cœur
  • 37,241
  • 25
  • 195
  • 267
randomThought
  • 6,203
  • 15
  • 56
  • 72
  • 2
    Did you just pick and choose parts from different enum examples? I'd like to see the calendar with a 4-day week named after the different card suits. – Mark Rushakoff Jul 16 '10 at 21:38
  • creating a prototype code generator and had a lot of stuff hard coded in there – randomThought Jul 16 '10 at 21:43
  • 2
    Please do not use the `using namespace std;` line in a header file but use the `std::` qualifier instead (see the first answeres in this post: http://stackoverflow.com/questions/1265039/using-std-namespace) – MKroehnert Jul 16 '10 at 21:48
  • 2
    Prefer to use include guards and identifiers without leading underscores. Leading underscores are reserved for compiler and implementations. Your identifiers and include guards may conflict with current or future versions of compilers. – Thomas Matthews Jul 16 '10 at 22:21
  • 1
    Also note: Using __Day__ is a bad idea. All identifiers that contain a doule underscore are reserved by the compilrt or OS and you may clash with http://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-a-c-identifier – Martin York Jul 16 '10 at 23:07

2 Answers2

5

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
  • 2,239
  • 2
  • 22
  • 32
  • Fixed the ostream duplication part. – randomThought Jul 16 '10 at 21:42
  • 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 Jul 16 '10 at 21:44
  • Shouldnt the #ifndef declarations protect against stuff in the header from being declared twice?? – randomThought Jul 16 '10 at 21:45
  • it works with the extern stuff, but im kinda confused as to why the #ifndef part isnt helping wit it being included twice – randomThought Jul 16 '10 at 21:46
  • 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 Jul 16 '10 at 21:46
  • 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 Jul 16 '10 at 21:47
  • @TP, it compiles each cpp standalone, so all the header files are read in. The #define for includes is to stop it including the header into the 1 cpp multiple times (like you did with vector & string), not to stop including into multiple cpp. – Greg Domjan Jul 16 '10 at 23:38
1

You're missing extern on the DayNames declaration.

kprobst
  • 16,165
  • 5
  • 32
  • 53