Mulitply defined symbols...

I'm doing something that seems pretty simple, but it's not working, maybe somebody could shed some light...

I have a header file which very simply defines some arrays with intialized values. I put preprocessor sentry code in there to the effect of:
#ifndef SAVE_TYPES
#define SAVE_TYPES

bla, bla
#endif

This should keep the compiler from compiling this twice, right? And yet I keep getting this error:
cpluginwindow.obj : error LNK2005: "char const * const  NB_Single_SFormatList" (?NB_Single_SFormatList@@3PBDB) already defined in cchildviewerwnd.obj
cpluginwindow.obj : error LNK2005: "char const * const  NB_Multi_SFormat" (?NB_Multi_SFormat@@3PBDB) already defined in cchildviewerwnd.obj
The header is included in two .cpps. Cpluginwindow.cpp CChildViewerWnd.cpp.

Any ideas?
BeatachonAsked:
Who is Participating?
 
trestanConnect With a Mentor Commented:
Use __SAVE_TYPE__ and try again to whether the problem still exists.
0
 
trestanCommented:
I found that if the symbol is redefined, an error message will be given at compile time. Have you tried Rebuild all? The NB_Single_SFormatList, NB_Multi_SFormat identifiers were defined in the headfile? char const * const is their type? If you like, please email me your project to: trestan@hotmail.com
0
 
BeatachonAuthor Commented:
Changing to __SAVE_TYPE__ didn't help. I just tried a rebuild all. The header looks something like this:

#ifndef __SAVE_TYPE__
#define __SAVE_TYPE__

#include <Othertypes.h>

/***************************************************************************/
/* Save format lists for multiple image formats                            */
/***************************************************************************/

LPCSTR         NB_Multi_SFormat = \
   "Bitmap (*.bmp)" "\0" "*.btif" "\0" \
   "All Files"                "\0"  "*.*"    "\0"  \
   "\0";

const int NB_Multi_nSFormat[] =
{
  NB_SAVE_BMP,
  NB_SAVE_ALL
};

#endif

No errors at compile time. Just at link time.
0
Cloud Class® Course: MCSA MCSE Windows Server 2012

This course teaches how to install and configure Windows Server 2012 R2.  It is the first step on your path to becoming a Microsoft Certified Solutions Expert (MCSE).

 
BeatachonAuthor Commented:
What's noteworthy is that it's gagging on NB_Multi_SFormat but NOT NB_Multi_nSFormat[]. Could there be a reson for this....?
0
 
tma050898Commented:
Beatachon,

I don't think you are going to be able to do what you want the way you are attempting to do it. I had a very similar situation where I wanted an initialized array of data in the header file, but also got linker errors. What I did was move the array to the .cpp file and provide access functions to the data in the header file.

If this turns out to be the way you want to handle this, lemme know and I'll post the code I'm referring to.

Tom
0
 
trestanCommented:
I think tma got the reason.
0
 
VEngineerCommented:

I assume that you want your arrays to be program-global (access from any file in the entire program), but you only want it to be defined once.  You cannot use the preprocessor to do this.

tma has experienced this problem in the past and is hitting right on it, but there is a simpler solution using external linkages if you do not want to encapsulate it.

For constant globals:
In one of your cpp files, DEFINE the constant using the extern keyword --
   extern const int NB_Multi_nSFormat[] =
   {
      NB_SAVE_BMP,
      NB_SAVE_ALL
   };

In the other cpp files that you use the array in, DECLARE it using a prototype after your preprocessor directives--
   extern const int NB_Multi_nSFormat[];

Then you will be able to access that constant within that file.

-----
For non-constant globals:
In one of your cpp files, DEFINE the global outside of all functions (extern keyword unnecessary)--

   int NB_Multi_nSFormat[] =
   {
      NB_SAVE_BMP,
      NB_SAVE_ALL
   };

In the other cpp files that you use the array in, DECLARE it using a prototype right after your preprocessor directives, extern required to indicate that it has been defined in another cpp file.
   extern const int NB_Multi_nSFormat[];

Then you will be able to access that global array (read and set the values) within that file.




0
 
tma050898Commented:
The method proposed by VEngineer is definitely a valid one. IMHO, I think the decision on which one would work in your application comes down to Do you want more of an object oriented encapsulation of the data or not. If not, then the extern keyword works perfectly. If you do want the encapsulation, then my idea would probably be the way to go. In either case, both solutions will accomplish what you need.

BTW, I had used VEngineer's method, but changed it so that I could validate the arguments being passed. This may or may not be a consideration for you.

Tom

0
 
VEngineerCommented:
I agree with tma totally.. the solution is dependent on your application needs.  Encapsulating a constant may not be too helpful, but encapsulating a global variable/object can prove to be beneficial.
0
 
tma050898Commented:
Exactly. Also, I guess I should have mentioned that I was encapsulating something similar to the NB_Multi_SFormat structure where several data members (as opposed to a single constant) were being contained. In my situation I also had two arrays where the elements of one array pointed into the second array. I think the only difference was that in your case, you only have to worry about a 1 to 1 correlation (which means that you can use the relative index values into the array) whereas in my situation, I was dealing with many to 1. Other than that, it looks pretty similar.
0
 
BeatachonAuthor Commented:
Yeah, this is the way I used to have it... in the .cpp. I didn't want to have to reproduce the same list in other source files for problems of maintaining synchronous data if something changes in one. It seems the problem is putting that code inside of a header.... guess it just can't be done.
Since you all understand what it is I'm trying to do, can anybody think of some other data structure that would fit these needs?
(I am trying to avoid the extern method, although it's the only way I can see right now.)
0
 
BeatachonAuthor Commented:
I've just thought of a way. I can put that data inside of the .cpp for my class, and then just add a member function to return a pointer to the beginning of the array. That should work. Thanks, guys.
tma - answer the question.....k?
0
 
tma050898Commented:
Beatachon,

I'm glad my comment/answer worked for you. However, I can't propose my comment as an answer because you accepted the proposed answer by trestan.

0
 
BeatachonAuthor Commented:
I've just thought of a way. I can put that data inside of the .cpp for my class, and then just add a member function to return a pointer to the beginning of the array. That should work. Thanks, guys.
tma - answer the question.....k?
0
 
BeatachonAuthor Commented:
OOOPS!
I did, didn't I? I'm gonna give you a question to answer. Answer it.
Thanks.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.