954,498 Members — Technology Publication meets Social Media
Username:
Password:
Lost login information?
Have something to say? Contribute New Article Reply to this Article

#ifndef/#define isn't working

Hello,
Here is my example code:

// Main.h

#ifndef MAIN_H
#define MAIN_H


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

string HelloWorld = "Hello World!\n";
void HelloEarth();

#endif
// Main.cpp

#include "Main.h"

int main()
{
    cout << HelloWorld;
    HelloEarth();
}
// Secondary.cpp
#include "Main.h"

void HelloEarth()
{
    cout << HelloWorld;
}

Problem is, it appears the #ifndef and #define tags aren't stopping Secondary.cpp from redeclaring HelloWorld.
When I attempt to compile and run, the IDE (in my case Code::Blocks) opens up a file called "locale_facets.tcc" and shows an error on line 2497.
This is the message I get for the error: obj\Debug\Main.o||In function `ZSt17__verify_groupingPKcjRKSs':|
C:\Program Files (x86)\CodeBlocks\bin\..\lib\gcc\mingw32\3.4.4\..\..\..\..\include\c++\3.4.4\bits\locale_facets.tcc|2497|multiple definition of `HelloWorld'|
obj\Debug\Secondary.o:C:\Program Files (x86)\CodeBlocks\bin\..\lib\gcc\mingw32\3.4.4\..\..\..\..\include\c++\3.4.4\bits\locale_facets.tcc|2497|first defined here|
||=== Build finished: 2 errors, 0 warnings ===|

Does anyone know what I did wrong?

Chuckleluck
Junior Poster in Training
54 posts since Sep 2011
Reputation Points: 10
Solved Threads: 1
 

Put the #ifndef around it.

thines01
Postaholic
Team Colleague
2,424 posts since Oct 2009
Reputation Points: 445
Solved Threads: 402
 

Put #ifndef around what?

Chuckleluck
Junior Poster in Training
54 posts since Sep 2011
Reputation Points: 10
Solved Threads: 1
 

You can't declare an instance of a variable more than once. That's what's happening. Try this:

// Secondary.h
#ifndef SECONDARY_H
#define SECONDARY_H

#include <iostream>
using namespace std;
#include <string.h>
extern string HelloWorld;

void HelloEarth();

#endif

Change Main.cpp and Secondary.cpp to include "Secondary.h", remove the function declaration of "HelloEarth" from Main.h, and remove the include for Main.h in Secondary.cpp. This allows you to declare the variable once in Main.h, and reference it from other places.

mcriscolo
Posting Whiz in Training
218 posts since Apr 2008
Reputation Points: 57
Solved Threads: 64
 
Put #ifndef around what?


HelloEarth()

thines01
Postaholic
Team Colleague
2,424 posts since Oct 2009
Reputation Points: 445
Solved Threads: 402
 

Ah thank you so much, both of you! =)

Chuckleluck
Junior Poster in Training
54 posts since Sep 2011
Reputation Points: 10
Solved Threads: 1
 

Problem is, it appears the #ifndef and #define tags aren't stopping Secondary.cpp from redeclaring HelloWorld.

Does anyone know what I did wrong?

Your include guard is correct, but it is designed for a different kind of problem, like this:

// Main.cpp

#include "Main.h"
#include "Main.h"

int main()
{
    cout << HelloWorld;
    //HelloEarth();
}


The above code will still compile fine because you've protected against Main.h being included more than oncein the same compilation unit.

Each CPP file is a separate compilation unit, so both Main.cpp and Secondary.cpp are going to be able to include Main.h , even with the include guard.

The error message actually says multipledefinition, not declaration. The problem isn't that you've declared HelloWorld in the header, it's that you've given it a value there. Because each CPP file includes the header separately, you've given it a value twice--this is what the compiler's complaining about.

You can stilldeclare HelloWorld in Main.h , and you must if you want to refer to it from multiple CPP files, but you can only give it a value in one place. It doesn't really matter where, as long as the file that contains the definition is compiled into the final executable.

Here's one way you could do it:

// Main.h

#ifndef MAIN_H
#define MAIN_H


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

extern string HelloWorld;
void HelloEarth();

#endif
// Main.cpp

#include "Main.h"

string HelloWorld = "Hello World!\n";

int main()
{
    cout << HelloWorld;
    HelloEarth();
}
// Secondary.cpp
#include "Main.h"

void HelloEarth()
{
    cout << HelloWorld;
}


Note the use of extern . That's basically telling the compiler, "Hey, there's a string called 'HelloWorld', but it's defined somewhere else." If you don't use this keyword, you'll get the same "multiple definition" error, because even if you don't give it a value explicitly, it still gets one--in this case, the empty string.

With extern , both Main.cpp and Secondary.cpp know that HelloWorld is a string and can use it as such. If you forget to give HelloWorld a value somewhere, you'll get a linker error--the compiler is perfectly happy.

gusano79
Posting Pro
519 posts since May 2004
Reputation Points: 182
Solved Threads: 77
 

Oh wow, you answered that very well. One other question: say a variable is declared extern in the global namespace. Will it still retain its value throughout all files it's used in? For example,

// Example.h
extern int a;
// Example1.cpp
#include "Example.h"
a = 10;
// Example2.cpp
#include "Example.h
cout << a;

Will it display 10 or will the value of a get lost between files?

Chuckleluck
Junior Poster in Training
54 posts since Sep 2011
Reputation Points: 10
Solved Threads: 1
 

say a variable is declared extern in the global namespace. Will it still retain its value throughout all files it's used in?

Will it display 10 or will the value of a get lost between files?

You still need to include the type of a in Example1.cpp , like this:

int a = 10;


If you put a main function around the code in Example2.cpp , it should display "10".

You can declare extern int a; any number of times, but you can only give it a value once, and that will be the value it starts with.

gusano79
Posting Pro
519 posts since May 2004
Reputation Points: 182
Solved Threads: 77
 

This question has already been solved

Post: Markdown Syntax: Formatting Help
You
View similar articles that have also been tagged: