Jump to content
  • Advertisement
Sign in to follow this  
DarkRonin

Confused as to why this wont compile

This topic is 2336 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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.

Share this post


Link to post
Share on other sites
Advertisement
Posted · Hidden
Hidden
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.

Share this post


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

Share this post


Link to post
Share on other sites
Put the
int Asset::nID=0;
line into a .cpp file instead of the header.

Share this post


Link to post
Share on other sites
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! Edited by TMarques

Share this post


Link to post
Share on other sites
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. Edited by Antheus

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites

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. Edited by wqking

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!