Hi,

I'm writing a "Date" class and it's fully functioning, including the output manipulators, but the issue I have is when creating a class the has a "Date" instance in it. It, then, doesn't compile because it says there are multiple definitions of the manipulator functions.

I'll lay out, below, the basic layout of my Date class (and supporting classes):

  • Date class
    • Header files
      • date.h (contains #includes for dateIOManip.h and dateManip.h)
      • dateIOManip.h (contains working code for IO manipulators)
      • dateManip.h (contains declarations for dateManip.cc)
      • day.h (contains declarations for day.cc)
      • month.h (contains declarations for month.cc)
      • time.h (contains declarations for time.cc...used in day.h)
      • year.h (contains declarations for year.cc)
    • Source files

************ The following is unwritten ************

  • Memo class
    • Header files
      • memo.h
    • Source files
  • Calendar class

************ The above is unwritten ************

The Date class, above, works alone. I can create instances of it in a main.cc and utilize everything within it well, including the IO manipulators.

But my goal is to use instances of it in the Memo class. And the Memo class will be used within my Calendar class above. Ultimately, to create a flexible text-based events calendar.

When I put an "#include date.h" (which includes dateManip.h and dateIOManip.h for a fully working Date class) within my memo.h, I get a long series of errors right at the end of compile time saying that the functions within dateIOManip.h have become multiple definitions within memo.o, and were first defined at dateIOManip.h

The following is a piece of my dateIOManip.h:

Date::FlagMap Date::Flags;

struct fullManip {};
void full(fullManip x) {}
typedef void(*fullPtr)(fullManip);
ostream &operator << (ostream &out, fullPtr) {
    Date::Flags[&out] = "full";
    return out;
}

ostream &operator << (ostream &out, Date &rhs) {
    string pick = "full";
    Date::FlagMap::iterator iter = Date::Flags.find(&out);
    if(iter==Date::Flags.end())
        pick = "full";
    else
        pick = iter->second;
    if(pick == "full")
        out << rhs.thisDay.strVal << ", " << rhs.thisMonth << " " << rhs.thisDay << ", " << rhs.thisYear;

(the above has MANY different manipulators, so it is not just a single manipulator)

The above working code would look like the following:

#include <iostream>
#include "date.h"

using namespace std;

int main(int argc, char** argv) {
    Date mine = Date(Month(12), Day(25), Year(2010));
    cout << full << mine << endl;
    cin.get();
    return 0;
}

The output from above would be:

Saturday, December 25, 2010

The error I get when I #include "date.h" within my memo.h is:

/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.4/include/g++-v4/new:105: multiple definition of `full(fullManip)'
build/Debug/GNU-Linux-x86/main.o:/home/josh/Calendar2/Date/dateIOManip.h:16: first defined here
build/Debug/GNU-Linux-x86/Memo/memo.o: In function `fullTime(fullTimeManip)':

Can someone help me correct this? I've been thinking of ways to work around this but I'm unsure what to do.

Also, I do have include guards on all of my header files (they're automatically placed there by NetBeans IDE)

PS: I work within Gentoo Linux on g++4.3.4

Thanks in advance!
-Josh

The following is a piece of my dateIOManip.h:

struct fullManip {};
ostream &operator << (ostream &out, fullPtr) {
    Date::Flags[&out] = "full";
    return out;
}

-Josh

Never ever put any definition with global linkage in the include file. An include file may contain only declarations.

Edited 6 Years Ago by nezachem: n/a

Never ever put any definition with global linkage in the include file. An include file may contain only declarations.

Blah...C++ For Dummies ftl. I found how to create my own output manipulators using that book, so I used it as a reference for writing these...not knowing the book assumed you were writing a simple program. Been fighting with it for a while now to no avail

Going to have to look over it carefully and see if I can do this another way...

Okay, solved this one

Extensive use of the extern keyword is needed for what I was doing to prevent multiple definitions of these functions

Original:

struct fullManip {};
void full(fullManip x) {}
typedef void(*fullPtr)(fullManip);
ostream &operator << (ostream &out, fullPtr) {
    Date::Flags[&out] = "full";
    return out;
}

It should be separated into a header and cc file
Modified (working) in header:

struct fullManip {};
extern void full(fullManip x);
typedef void(*fullPtr)(fullManip);
extern ostream &operator << (ostream &out, fullPtr);

in the cc file:

void full(fullManip x) {}
ostream &operator << (ostream &out, fullPtr) {
    Date::Flags[&out] = "full";
    return out;
}

Doing the above to all the places I had complaints does allow the code to compile and link successfully

Edited 6 Years Ago by josolanes: n/a

It sounds to me like you need header guards in place as well. That way, if a specific header somehow gets #included more than once, the various instances of it aren't butting heads and you only get one set of definitions.

#ifndef HEADER_FILE_NAME  //check for previous inclusion
#define HEADER_FILE_NAME //make it known that it's being included

/* ... your code here ... */

#endif //okay, I'm done now...

Edited 6 Years Ago by Fbody: n/a

It sounds to me like you need header guards in place as well. That way, if a specific header somehow gets #included more than once, the various instances of it aren't butting heads and you only get one set of definitions.

#ifndef HEADER_FILE_NAME  //check for previous inclusion
#define HEADER_FILE_NAME //make it known that it's being included

/* ... your code here ... */

#endif //okay, I'm done now...

I had header guards up as well, which is what really had me scratching my head when I ran into the problem. Quite a bit of searching led me to the extern keyword, which doesn't seem to be used very often...but did help me in this case

Thanks for the reply though, Fbody :)

This question has already been answered. Start a new discussion instead.