Solved

Mulitply defined symbols...

Posted on 1998-07-09
15
219 Views
Last Modified: 2013-11-19
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?
0
Comment
Question by:Beatachon
  • 6
  • 4
  • 3
  • +1
15 Comments
 
LVL 8

Accepted Solution

by:
trestan earned 50 total points
ID: 1318934
Use __SAVE_TYPE__ and try again to whether the problem still exists.
0
 
LVL 8

Expert Comment

by:trestan
ID: 1318935
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
 

Author Comment

by:Beatachon
ID: 1318936
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
 

Author Comment

by:Beatachon
ID: 1318937
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
 
LVL 3

Expert Comment

by:tma050898
ID: 1318938
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
 
LVL 8

Expert Comment

by:trestan
ID: 1318939
I think tma got the reason.
0
 
LVL 2

Expert Comment

by:VEngineer
ID: 1318940

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
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 3

Expert Comment

by:tma050898
ID: 1318941
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
 
LVL 2

Expert Comment

by:VEngineer
ID: 1318942
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
 
LVL 3

Expert Comment

by:tma050898
ID: 1318943
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
 

Author Comment

by:Beatachon
ID: 1318944
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
 

Author Comment

by:Beatachon
ID: 1318945
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
 
LVL 3

Expert Comment

by:tma050898
ID: 1318946
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
 

Author Comment

by:Beatachon
ID: 1318947
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
 

Author Comment

by:Beatachon
ID: 1318948
OOOPS!
I did, didn't I? I'm gonna give you a question to answer. Answer it.
Thanks.
0

Featured Post

What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
while loop over for loop 7 80
fizzArray  challenge 1 49
sumHeights  challenge 17 61
noX challenge 17 77
Introduction: Load and Save to file, Document-View interaction inside the SDI. Continuing from the second article about sudoku.   Open the project in visual studio. From the class view select CSudokuDoc and double click to open the header …
Exception Handling is in the core of any application that is able to dignify its name. In this article, I'll guide you through the process of writing a DRY (Don't Repeat Yourself) Exception Handling mechanism, using Aspect Oriented Programming.
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
Sending a Secure fax is easy with eFax Corporate (http://www.enterprise.efax.com). First, Just open a new email message.  In the To field, type your recipient's fax number @efaxsend.com. You can even send a secure international fax — just include t…

747 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now