Confused as to why this wont compile

Started by
12 comments, last by Muzzy A 11 years, 11 months ago
Hi Guys,

I am scratching my head at the moment with this one.

I have a class which I have stripped right back to bare bones trying to work out why it wont compile in my app.


#pragma once
class Asset
{
public:
Asset()
{
++(this->nID); // Asset ID (auto-increments)
}
~Asset()
{
}
private:
static int nID;
};
int Asset::nID=0;


When I compile in my main application I get the following error;

"private: static int Asset::nID" ([email="?nID@Asset@@0HA"]?nID@Asset@@0HA[/email]) already defined in framework.obj

I have taken the above and put it into a brand new C++ project and it compiles fine.

I cant understand why it wont compile in the 'primary' application I am working with.

Even if I change the nID variable to something else, then the new variable name is 'already defined'. So, it isn't a variable redefinition problem.

Any ideas on this would by hugely appreciated.
Advertisement
Hi Guys,

I am scratching my head at the moment with this one.

I have a class which I have stripped right back to bare bones trying to work out why it wont compile in my app.


#pragma once
class Asset
{
public:
Asset()
{
++(this->nID); // Asset ID (auto-increments)
}
~Asset()
{
}
private:
static int nID;
};
int Asset::nID=0;


When I compile in my main application I get the following error;

"private: static int Asset::nID" ([email="?nID@Asset@@0HA"]?nID@Asset@@0HA[/email]) already defined in framework.obj

I have taken the above and put it into a brand new C++ project and it compiles fine.

I cant understand why it wont compile in the 'primary' application I am working with.

Even if I change the nID variable to something else, then the new variable name is 'already defined'. So, it isn't a variable redefinition problem.

Any ideas on this would by hugely appreciated.
try setting the value inside the class or something

o3o

"int Asset::nID=0;" is defining the variable.
So put it into a .cpp file rather than header.

https://www.kbasm.com -- My personal website

https://github.com/wqking/eventpp  eventpp -- C++ library for event dispatcher and callback list

https://github.com/cpgf/cpgf  cpgf library -- free C++ open source library for reflection, serialization, script binding, callbacks, and meta data for OpenGL Box2D, SFML and Irrlicht.

Put the
int Asset::nID=0;
line into a .cpp file instead of the header.
Don't know if that's the whole header file you posted here but, in case it is, it's best practice to wrap the code in a header with "#ifndef" directives.

example: name_of_file.h

#ifndef NAME_OF_FILE_HEADER
#define NAME_OF_FILE_HEADER
//Put your code here...
#endif


If you don't do this you may have conflict issues when compiling.

Good luck!
Tiago.MWeb Developer - Aspiring CG Programmer
Source code (a.cpp, x.h) --(preprocessor)--> compilation_unit ---(compiler)--> a.o/.obj
Source code (b.cpp, x.h) --(preprocessor)--> compilation_unit ---(compiler)--> b.o/.obj --(linker)--> executable
Source code (c.cpp, x.h) --(preprocessor)--> compilation_unit ---(compiler)--> c.o/.obj


cpp file #includes header (.h) files. Compiler then converts stuff in those into code and symbols. nAssets is a symbol. At that point it's just a reference to something unknown, compiler doesn't care about it beyond a name.

Since each cpp is processed independently, we end up with 3 object files, each containing their own copy of nAssets. When linker puts all 3 together, it has 3 copies of nAssets.

By putting nAssets into .cpp file, such as (a.cpp), it will only generate one symbol, avoiding the confusion.

Header guard (pragma once) only prevents inclusion into same compilation unit. If x.h is included multiple times when preprocessing a.cpp, it will only appear the first time. But it will be included fully again when preprocessing b.cpp and c.cpp.

int Asset::nID=0;[/quote]This line actually says: "reserve 4 bytes inside executable at precisely this location. When someone needs nAssets symbol, give them this pointer".

Unlike most other languages, it's more than just semantic annotation, it's fairly important choice on where to put it.

it's best practice to wrap the code in a header with "#ifndef" directives.[/quote]

It is, but pragma once is fairly well supported these days and does the same. I prefer header guards myself.
Putting the variable into a CPP file did the job.

I still don't understand why a straight cut and paste of the same code into a new project worked ok, though. Must be one of those strange compiler things.

Thanks guys, I was starting to tear my hair out.

I still don't understand why a straight cut and paste of the same code into a new project worked ok, though. Must be one of those strange compiler things.

Definition in header will work as long as the header is included in only one CPP.
That's to say, the definition is in only one translate unit.
If the header is included in more than one CPPs, it won't link due to duplicated definition.

https://www.kbasm.com -- My personal website

https://github.com/wqking/eventpp  eventpp -- C++ library for event dispatcher and callback list

https://github.com/cpgf/cpgf  cpgf library -- free C++ open source library for reflection, serialization, script binding, callbacks, and meta data for OpenGL Box2D, SFML and Irrlicht.


I still don't understand why a straight cut and paste of the same code into a new project worked ok, though. Must be one of those strange compiler things.



Because your new project probably either a) only includes the header once or b) you copied the class into a cpp file.

Read Antheus's post again.
if you think programming is like sex, you probably haven't done much of either.-------------- - capn_midnight

This topic is closed to new replies.

Advertisement