PDA

View Full Version : C++: Multiple declarations?




Soulstorm
Jun 26, 2006, 02:08 AM
I am giving you the source of a little program I made. It's a bank simulation. The problem is that when I turn zerolink off in XCode, I get a bunch of errors about multiple declarations. The problem is that I have not declared anything more than once, and I have also put #ifndef in all headers!

Can you please take a look at it? And also, can you tell me why the program gives many more errors in GCC 3? I thought I had done everything right.



Soulstorm
Jun 26, 2006, 05:37 AM
Hm... I was forced to rewrite the whole application from scratch using classes. Here is what I have got:

It seems that now I haven't got these zero-link errors... I used a pre-compiled header this time.

I would appreciate it if you had a look at it and tell me if that was the best way of doing it (the program is MUCH smaller and comprehensive, compared to the last one.)

iSee
Jun 26, 2006, 10:27 AM
I only looked at the second set of source code, so I'm not comparing the two versions. So:

The code is clean, organized and straightforward, so that's a good design. :) The code is "self-documenting" (i.e. what it does and how it works is apparent from the code itself), so you don't need to add significant comments, in my opinion (although if this is for a class, your professor's opinion is the only one that counts :D ). I didn't debug it or anything, but I can tell from looking at it that you don't have any major problems. :) :)

One thing about includes, though, and this may have been the source of your link problems before:

1. A small thing: Change the name of functions.cpp to functions.h. The way you are using it, it is really an include file, not a source file. Also. In your project you should make sure it is not being compiled as a source file. (It probably isn't because you'd be getting link errors if it was.

2. declare the getval functions as inline:

...
inline void getval(int *a){
...
inline void getval(float *a){
...

This will stop the link errors if you include functions.cpp (should be .h) in more than one place. You are getting around this now by including functions.cpp (.h) only once in main.cpp, but then you have to declare getval() manually in bank.cpp. This way you will be able to #include functions.h in both main.cpp and bank.cpp, which is the better way to do it.
--------
On the other hand, if you don't want to make the getval() functions inline, you could leave functions.cpp as is, and:
1. Add a functions.h that delcares the getval() functions (just declares them, no function body):

#ifndef FUNCTIONS_H
#define FUNCTIONS_H
// ...comments...
void getval(int *a);
void getval(float *a);
#endif

2. Make sure functions.cpp is compiled as a source file, and remove the #ifndef FUNCTIONS_CPP stuff, which is header file stuff.

-------
I'm guessing that previously the bodies of the getval() functions appeared in more than one source file. This will cause link errors because a function with a particular name and set of parameters can only occur once in an executable. The exception to that rule is inline functions, which can appear multiple times.

Soulstorm
Jun 26, 2006, 04:35 PM
Hey, thanks a lot!

Lots of new stuff here... I'm going to have many things to try tomorrow to optimize the code.

Actually, this is not an assignment. I intend to use this command-line program as the basis for a program with GUI. I have already done this using Cocoa, but then I realized the code for my C++ project was very old, so I decided to update it. I ended up rewriting it because it was really messed up (it was written during my early stages in C++).

Thanks a lot for your answer, and for the time you took to have a look at my code. I will check the things you said, and I will make some test programs to understand everything.

PS: iSee, are you Greek? From the style of your writing, I get the feeling that you are!

Soulstorm
Jun 27, 2006, 02:26 AM
On the other hand, if you don't want to make the getval() functions inline, you could leave functions.cpp as is, and:
1. Add a functions.h that delcares the getval() functions (just declares them, no function body):

#ifndef FUNCTIONS_H
#define FUNCTIONS_H
// ...comments...
void getval(int *a);
void getval(float *a);
#endif

2. Make sure functions.cpp is compiled as a source file, and remove the #ifndef FUNCTIONS_CPP stuff, which is header file stuff.

-------
I'm guessing that previously the bodies of the getval() functions appeared in more than one source file. This will cause link errors because a function with a particular name and set of parameters can only occur once in an executable. The exception to that rule is inline functions, which can appear multiple times.
I did what you said about the functions.h file, but I end up with an error... I made a functions.h file, I removed the #ifndefs from the .cpp file, and added them appropriately to the .h file. When I tried to include the .h file on both the main() and the bank.cpp, it returned me these errors:
Tool:0: collect2: ld returned 1 exit status
Tool:0: /Users/soulstorm/xcode/intermediate files/C++ tool 3.build/Debug/C++ tool 3.build/Objects-normal/ppc/Bank.o reference to undefined getval(float*)
Tool:0: /Users/soulstorm/xcode/intermediate files/C++ tool 3.build/Debug/C++ tool 3.build/Objects-normal/ppc/main.o reference to undefined getval(int*)
Tool:0: Undefined symbols:
Tool:0: getval(float*)
Tool:0: getval(int*)
Tool:0: waitForInput()
Tool:0: /Users/soulstorm/xcode/intermediate files/C++ tool 3.build/Debug/C++ tool 3.build/Objects-normal/ppc/main.o reference to undefined waitForInput()


Why is that? Can you check it?

iSee
Jun 27, 2006, 05:23 PM
I think functions.cpp is not added to the project.
Is it getting compiled and linked with the project?
Those errors make me think it is not getting linked in.

Also, regarding your other post: You're welcome! I see you post a lot in this forum, helping others, so that makes me especially happy to try to help you. (Not that I wouldn't try to help someone I haven't noticed posting a lot, but you know what I mean.) I'm not Greek--I'm American--but since you are, I'll take that as a compliment :D

Soulstorm
Jun 28, 2006, 03:06 AM
The functions.cpp is not getting compiled, unless I write "#include functions.cpp" instead of "#include functions.h" in the main.cpp file.

Should this happen? I thought that the header files were meant to be included, not the source files. And also, this way the headers files are useless. If that way I include the source file functions.cpp 2 times in my project I will end up with an error again, so I know that the header file doesn't work this way.

iSee
Jun 28, 2006, 08:39 AM
The functions.cpp is not getting compiled, unless I write "#include functions.cpp" instead of "#include functions.h" in the main.cpp file.

Should this happen? I thought that the header files were meant to be included, not the source files. And also, this way the headers files are useless. If that way I include the source file functions.cpp 2 times in my project I will end up with an error again, so I know that the header file doesn't work this way.

You want functions.cpp to get compiled and linked into your executable, the same way your other .cpp files are. How exactly you do that depends on the IDE (if any) you are using (it must be Xcode, of course). For some reason I can't remember exactly how to add a .cpp to an Xcode project so that it is compiled and linked, and I don't have a Mac here, but set it up just like Bank.cpp and Account.cpp.

Soulstorm
Jun 28, 2006, 03:08 PM
I have redone the project from the beginning, I removed the precompiled header and ran the program. It ran flawlessly in both Xcode and Dev C++. I only wish I knew what had I done wrong...

Here is the code. Thanks for your help!

iSee
Jun 29, 2006, 11:10 AM
Good!
Sometimes IDEs and get confused, so maybe removing functions.cpp from the project and then adding it again would have fixed it. You may already know all this but: The way a .cpp file gets incorporated into an executable, there is a two step process:
1) The .cpp is compiled to object code (usually either a .o or .obj file).
2) Then all the .o/obj files from all of the .cpp files for the project, along with libraries and possibilty other stuff is linked together into the app.
So here's a sample of doing it manually at the command line (NOTE: this is simplified--without all the proper command line options):

gcc source1.cpp -- creates source1.o from source1.cpp
gcc source2.cpp -- creates source2.o from source2.cpp
link source1.o source2.o -output:myapp -- creates myapp from the .o files

The IDE's are nice because they automate this for you, and they also figure out dependencies for you (like if source1.cpp #includes somefile.h, the IDE automatically knows to recompile source1.cpp when somefile.h changes, which, in turn, causes it to rebuild myapp because source1.o has been updated). All you have to do is add a .cpp file to your project and it will (or should) detect dependencies and (should) ensure the file is compiled and linked, when appropriate).

It looks like the IDE got confused somewhere, and was not treating your functions.cpp as a c++ source file, like it should have.

Anyway, I'm glad it's working...