Keep gettin Linker errors with namespaces in C++

Started by
9 comments, last by Janju 18 years, 10 months ago
Can anyone help me on this:
------ Rebuild All started: Project: console03, Configuration: Debug Win32 ------

Deleting intermediate files and output files for project 'console03', configuration 'Debug|Win32'.
Compiling...
stdafx.cpp
Compiling...
nmino.cpp
console03.cpp
Generating Code...
Linking...
nmino.obj : error LNK2005: "int history::rotateCCW" (?rotateCCW@history@@3HA) already defined in console03.obj
nmino.obj : error LNK2005: "int history::rotateCW" (?rotateCW@history@@3HA) already defined in console03.obj
nmino.obj : error LNK2005: "int history::moveRight" (?moveRight@history@@3HA) already defined in console03.obj
nmino.obj : error LNK2005: "int history::moveLeft" (?moveLeft@history@@3HA) already defined in console03.obj
nmino.obj : error LNK2005: "int history::moveDown" (?moveDown@history@@3HA) already defined in console03.obj
nmino.obj : error LNK2005: "int history::moveUp" (?moveUp@history@@3HA) already defined in console03.obj
nmino.obj : error LNK2005: "int history::nothing" (?nothing@history@@3HA) already defined in console03.obj
Debug/console01.exe : fatal error LNK1169: one or more multiply defined symbols found

Build log was saved at "file://d:\dev\cxx\console\console03\console03\Debug\BuildLog.htm"
console03 - 8 error(s), 0 warning(s)


---------------------- Done ----------------------

    Rebuild All: 0 succeeded, 1 failed, 0 skipped
I use VC++ 2003, this is how the file looks:
#ifndef INIT_H
#define INIT_H

namespace history
{
	int nothing   = 0;
	int moveUp    = 1;
	int moveDown  = 2;
	int moveLeft  = 3;
	int moveRight = 4;
	int rotateCW = 5;
	int rotateCCW = 6;
};

#endif;
Advertisement
You shouldn't declare globals in a header file. They belong in a source file. But to make them visible outside of that source file, you use the extern keyword in the header when declaring them:

Init.h
#ifndef INIT_H#define INIT_Hnamespace history{	extern int nothing;	extern int moveUp;	extern int moveDown;	extern int moveLeft;	extern int moveRight;	extern int rotateCW;	extern int rotateCCW;};#endif;

Init.cpp
#include "Init.h"int history::nothing   = 0;int history::moveUp    = 1;int history::moveDown  = 2;int history::moveLeft  = 3;int history::moveRight = 4;int history::rotateCW  = 5;int history::rotateCCW = 6;

If you don't do it like this, then it will end up reserving space for the variables in every single .cpp in which the header file is included. Then you have multiple copies of the global variables, and the linker doesn't know which one to use when it combines all the .cpps' object files into a single executable.
"We should have a great fewer disputes in the world if words were taken for what they are, the signs of our ideas only, and not for things themselves." - John Locke
Ok Agony. If been using classes full of statics in my programms so far, because i never got the namespace to "work" as i expected them to work.

If i have to split things up again in h/cpp file with namespaces then they are not much of a relief to me. Maybe i should stick with my style. ... :|

Thanks for your time/help. :)
ok another question about namespaces.

Is this code ok memory wise:
#ifndef INIT_H#define INIT_Hnamespace history{	static const int nothing = 0;	static const int moveUp = 1;	static const int moveDown = 2;	static const int moveLeft = 3;	static const int moveRight = 4;	static const int rotateCW = 5;	static const int rotateCCW = 6;};#endif;
Constants don't take up any memory. Even if they did, that's just 6 ints... nothing to lose sleep over.

Declaring them static, when you've put them in a header file, is completely pointless.
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
Quote:Original post by Fruny
Constants don't take up any memory. Even if they did, that's just 6 ints... nothing to lose sleep over.

Declaring them static, when you've put them in a header file, is completely pointless.
Well but doing so will allow me to complile this stuff in VC++2003. Without the statics it won't.

Why do you think it's pointless?

Using the keyword external in a namespace feels somehow weird to me.

[Edited by - Jonus on June 9, 2005 8:39:09 AM]
*bump*
You might try with enums. Only downside, this restricts your constants to integers:

namespace history{  enum eConstants  {    nothing = 0,    moveUp,    moveDown,    moveLeft,    moveRight,    rotateCW,    rotateCCW,    ArbitraryValue = 17,  };}


You can also set every single enum to a specific value. I use enums a lot for flag values.

Fruny: Ftagn! Ia! Ia! std::time_put_byname! Mglui naflftagn std::codecvt eY'ha-nthlei!,char,mbstate_t>

Quote:Original post by Endurion
You might try with enums. Only downside, this restricts your constants to integers:

namespace history{  enum eConstants  {    nothing = 0,    moveUp,    moveDown,    moveLeft,    moveRight,    rotateCW,    rotateCCW,    ArbitraryValue = 17,  };}


You can also set every single enum to a specific value. I use enums a lot for flag values.
Hi there Endurion. I have been using enums a lot in the past. I can't remember what it was, but something with them did really bug me back then. I don't know what it was, maybe something with the switch(){} case or anything else - can't remember. But i had to rewrite alot of stuff because of it.

The best thing for things like this (if both key and value are equivalent in use) would probly be a map, but i don't think i need to go that far (this time).
Quote:Original post by Jonus
Quote:Original post by Fruny
Constants don't take up any memory. Even if they did, that's just 6 ints... nothing to lose sleep over.

Declaring them static, when you've put them in a header file, is completely pointless.


Well but doing so will allow me to complile this stuff in VC++2003. Without the statics it won't.

Why do you think it's pointless?


The first reason being is using the keyword static to make an internal linkage is deprecated in C++, that pre-dates C++ standardization, if you want to do that then would use anonymous namespaces.

Secondly and i think what Fruny is trying to get at making an internal linkage in headers makes every translation unit have its own version but because they are real constants (because they are defined in the header) it makes no difference.

Yes you have two kinds of constants, real ones, and logically constant, former consumes no storage while the latter does but is read-only. And it all depends on the context which will be which.

Quote:Original post by Jonus
Using the keyword external in a namespace feels somehow weird to me.


Get use to it [wink], perhaps you should understand what exactly extern does.

This topic is closed to new replies.

Advertisement