Problem linking in C++ and visual studio 2005 [solved]

Started by
3 comments, last by Nypyren 15 years, 3 months ago
im trying to program something, and seperate every class to files .cpp and .h, however, when im linking i have serious problems. i have a few classes.. AudioClass, and SoundFile.. and etc and i wanted to make instances of all these classes global. so i made globalVariables.h - all the variables i declared there are being loaded when the program starts. providing them to all the functions in a non-global way is too much "messing around" and i'd like them to be global. since each one of them affects almost the entire program. the other reason for them to be global is because i have some function which i cannot pass serveral arguments, so i also need to package these all into one argument, which becomes another messing around. i wanted the structure of the program to be like that. each class in its own file, and almost all the classes will have their instance globally, and i have a few files which supposed to deal with those global instances. these "few files" are bound with the AudioClass. since the mother function of dealing with those global instances, is called from the AudioClass. instead of helping me out, C++ and the visual studio linker decides to put all his weight on me. and giving me errors of "already defined" things. i provide a scheme for all the files and my links. i used header inclusion guards for every header file i have. this is why i wonder why things are messing. in this example, its working good. (if you have problems with the images tell me) edit : ive noticed i forgot to paint the link between the AudioClass.cpp to the audioFunction.h . maybe i'll add it later, because im late for a class at the moment. but once i link other file to the globalVariables.h, i instantly getting "already defined" errors. example 1 : example 2 : example 3 : i will appreciate your help. thanks. i would like to stay with the current structure, as i wouldn't want those "technical" things to affect me and the tidyness of the project. [Edited by - itay390 on January 21, 2009 10:58:32 AM]
Advertisement
I believe the answer is that you should not "define" things in header files. You only want to 'declare'.

"Defining" a variable means you make a physical instance of it. "Declaring" something means you are simply describing what it is named and how it is used.


For example, if you do this in a header file:

#ifndef _HEADER_H#define _HEADER_Hint i;#endif



You get a separate copy of the "int i;" in every C++ file that gets compiled (because #include really is just copy-pasting the header into the C++ file at compile time).

The header guards only prevent a SINGLE C++ file from including a header more than once. Separate C++ files do not prevent each other from #including.

Now, replace the "int i;" with your global AudioClass and SoundFile variables, and this is what is happening.

Then, when the linker tries to put all of it together, it sees one separate variable in each of the C++ files, but they're all named the same thing and it doesn't know how to glue them all together! (the linker is very dumb.)


The easiest solution is to use "extern" to convert the definition into a declaration.

#ifndef _HEADER_H#define _HEADER_Hextern AudioClass *audioClass; // or whatever.#endif


This turns the line from a "define" into a "declare" and means that you don't get multiple physical copies of the variable.

Important: Once you turn something into an "extern", you need to put a physical define for it in ONE C++ file, otherwise you will get "unresolved external reference" errors from the linker.

So in your AudioClass.cpp file, you would have:

#include "GlobalVariables.h"AudioClass *audioClass;// and a bunch of other code for your class.



This way, all of your code that includes your header will know that SOMEWHERE, there will be a definition of the audioClass, but it's not known until linking time.

Then, when the linker glues everything together, you only have one AudioClass and everything that was #including the "extern" declaration will be fixed by the linker to use the ONE AudioClass you end up with.



Also: You might enjoy GraphViz - it can help you render nice diagrams like those much more quickly. You make a text file that describes your graph, and GraphViz calculates the layout and then renders it to an image file.

[Edited by - Nypyren on January 21, 2009 2:27:17 AM]
oh, thank you very much. this seems like an easy solution and it did not require any change to my structure.
however in my mind i thought that the "one cpp" file i would define (physically) the global variables will be globalVariables.cpp
i'll define them like this in globalVariables.cpp :

AudioClass audioclass;
std::list<PlayingSound> playingSoundList;
and etc.

when i will get home from college, i will report if it worked.
it worked!
thanks again.
Quote:Original post by itay390
however in my mind i thought that the "one cpp" file i would define (physically) the global variables will be globalVariables.cpp


Yeah, that's perfectly fine. The linker doesn't care which C++ file you use for the definition - you are free to put those definitions anywhere that makes the most sense to you.

This topic is closed to new replies.

Advertisement