duplicate symbol problem on linking


Ryan Ringle
11-14-2007, 05:26 PM
Greetings,
I have a problem whose solution is hopefully obvious to the more experienced c++ programmers out there. I have a main.cpp which includes header files for two classes, both of which require interp_1d. Upon linking there is an error that the two object files contain the duplicate symbol Base_interp::hunt(double). I imagine this has something to do with the fact that both classes include interp_1d.h. Is there any way to fix this without combining the two classes into one? Any help would be appreciated. Thanks!

Bill Press
11-16-2007, 05:08 PM
Hello, Ryan.

A perhaps controversial design decision that we had to make in NR3 is that the *.h files contain not just declarations, but also definitions. See this thread (http://www.nr.com/forum/showthread.php?t=1260) for some discussion of both sides of the issue. Basically, because we frequently use templates, it is hard (and confusing pedagogically) to try to maintain the "declarations only" convention in *.h files.

A consequence is that the typical NR3 *.h file can be included only once, and it must be in the same compilation unit as anything that uses it. If you really need to compile your two classes separately, then you'll need to edit the interp_1d.h file into separate declaration and definition files; then you can include the declaration file more than once, and compile the definition file along with your other files.

A better solution for most NR3 users is to compile the parts of your program that use NR3 as a single unit: Make a file something like:

#include "nr3.h"
#include "interp_1d.h"
#include "your_first_class.h" [or .cpp, makes no difference]
#include "your_second_class.h" [or .cpp]
[another other files that use NR3 routines]
...
int main()
[your main routine]

Use this file as your "main" file. Be sure to remove the files included above from your compile command or project file list, and be sure *not* to have any NR3 includes in your class files. You can link to any other code referenced by your classes or main, as long as it doesn't reference NR3 routines.

Apologies if this doesn't completely meet your needs, but, as I said, we had to make some choices.

Cheers,
Bill P.

Ryan Ringle
11-17-2007, 02:18 PM
Thanks, Bill...
I understand the need to make the decisions that you did. The option which you presented will suit my needs perfectly with a little recoding. Thank you for your assistance and a great product. Although I have yet to use NR3 extensively, I notice a vast improvement in ease of use over previous versions. Keep up the good work!

Ryan

dixond
11-26-2013, 10:34 AM
Bill,

I cannot put all of my code in single unit even with a major refactorization effort. I am using the adapt.h tool and I have two classes that require

#include "adapt.h"

which will not work for reasons previously discussed.

I would greatly appreciate further explanation of the following:

"If you really need to compile your two classes separately, then you'll need to edit the interp_1d.h file into separate declaration and definition files; then you can include the declaration file more than once, and compile the definition file along with your other files."

I am an intermediate level c++ programmer and was unsuccessful in trying to separate the definitions into a *.c file. The code compiled but I wound up with additional symbol issues we I ran my application. I found the following at cplusplus.com

"Because templates are compiled when required, this forces a restriction for multi-file projects: the implementation (definition) of a template class or function must be in the same file as its declaration. That means that we cannot separate the interface in a separate header file, and that we must include both interface and implementation in any file that uses the templates."

Being able to pass functors was extremely helpful, but I am starting to get the impression that I will need to change adapt.h significantly if I break up the definitions and declarations (that is, I will have to remove templating).

Is there any way to resolve this issue without making major changes to adapt.h? Can you provide an example of what your *.cpp and *.h would look like after splitting.

Thanks,

David