Link to home
Start Free TrialLog in
Avatar of shaolinfunk
shaolinfunkFlag for United States of America

asked on

Need help with #include...I keep getting a "multiply defined symbols found" error

If you see the previous related questions that I asked I have created a very simple app called "FirstApp", a dialog-based MFC app in VS2008.  It contains FirstAppDlg.cpp, FirstApp.cpp, and Function.cpp (something I added).  The 3 .cpp files each have respective header .h files.

Here's the error message I get....
Linking...
1>Function.obj : error LNK2005: "class std::vector<struct Data,class std::allocator<struct Data> > vData" (?vData@@3V?$vector@UData@@V?$allocator@UData@@@std@@@std@@A) already defined in FirstAppDlg.obj
1>C:\Documents and Settings\Administrator\Desktop\FirstApp\Debug\FirstApp.exe : fatal error LNK1169: one or more multiply defined symbols found

Below I've included the top portion of the 3 .cpp and 3. h files.  I suspect something is wrong with my include statements.  Can someone please show me what I'm doing wrong?
// FirstAppDlg.cpp : implementation file

#include "stdafx.h"
#include "FirstApp.h"
#include "FirstAppDlg.h"
#include "Function.h"


// FirstAppDlg.h : header file

#pragma once


// FirstApp.cpp : 

#include "stdafx.h"
#include "FirstApp.h"
#include "FirstAppDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// FirstApp.h : 

#pragma once
#ifndef __AFXWIN_H__
	#error "include 'stdafx.h' before including this file for PCH"
#endif
#include "resource.h"		// main symbols


// Function.cpp

#include "stdafx.h"
#include "Function.h"


// Function.h

#pragma once
#include <string> 
#include <math.h>
#include <vector>
#include <fstream>

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of Zoppo
Zoppo
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of pasolo
pasolo

Use #pragma one in every header file as first instruction on top.

No need for  
#ifndef __AFXWIN_H__
      #error "include 'stdafx.h' before including this file for PCH"
#endif

These are deprecated and "pragma once does the same job
Avatar of shaolinfunk

ASKER

pasolo...if you look at my header files in the attached code snippet above...i already have #pragma once in every header at the top (there are only 3 header files involved here)
pasolo, #pragma once is proprietary for ms and normal header protections are not deprecated.

the preprocessor statements you posted are not header protection but ms preprocessor code in generated headers which should make sure that stdafx.h was included before that header.

Sara
zoppo....i don't know whether a variable is global or not....but your solution works...while i see what you did i don't understand this concept of "extern"...what is this?
shaolinfunk, look at zoppo's comment. your problem is that you must not define (only declare) variables in header or the linker complains if the header was included in two cpp files.

instead of using extern you may consider moving the vector to a class as member.

Sara
I defined vector < struct Data > vData in Function.h.  To me I think this means that any function in Function.cpp may access vData.  Does that make it a global variable when only functions defined in Functions.cpp may access it?  And not any functions in the other .cpp files?
the extern turns a definition of a variable to a declaration. so the compiler knows what type the variable is but it doesn't reserve memory for it. if you declare variables as extern you need exactly one cpp file where the variable is defined globally that means outside of any function.

Sara
Sorry, shaolinfunk you are 100% right.
Are you including namespace std anywhere?


@sarabande: Yeap, but we are dealing with VS here and it is deprecated in VS
Hi Sara!

Thanks for your comment.  I think I see what you're saying..but in the related questions (that this question is an offspring of) Zoppo made clear that for this simple app of mine, FirstApp, classes were not needed.

Since I do plan on adding more variables in the future I think classes are the way to go.  

Zoppo, I am thinking of re-posting my earlier question and asking if it can be rewritten using classes this time...What do you think?
as told if you don't use extern or have the variable a member of a class, it is a definition of a global variable and every cpp file that includes the header would add a further symbol with that name to the list of definitions.

a good way out normally is to have

// functions.h

struct Vdata
{
    static std::vector < struct Data > vData;
};

// functions.cpp

 ...
 std::vector < struct Data > Vdata::vData;


then everyone can use the vector by including functions.h and like

   Vdata::vData.push_back(data);

Sara
I think you should try to understand how compiler and linker work together to understand what happens here:

The compiler compiles each CPP file in your project - before this is done the preprocessor processes every #include/#define/#ifdef/a.s.o. so in fact the compiler finally compiles one single file which contains everything included in the CPP file. Now, including a header with a instantiated variable into two CPP files leads to two identically instantiated variables. After compiling finished the linker tries to collect all information to put it into the binary (EXE or LIB or DLL) and finds two variables with the same name, so it generates the error.

Using 'extern' tells the compiler 'this is not the instance itself but there exist an instance anywhere', so the compiler generates code wherever the variable is accessed correctly and the linker later can resolve all these accessing code to that one and only instance.

> I am thinking of re-posting my earlier question and asking if it can be rewritten using classes this time...What do you think?
In general I agree, but before you decide this finally I would suggest you think a little bit about what your final goal is in order to find best decision about how your project/code should be designed. If you want you can simply tell us here what you expect your program to be at the end, then we can give you hints on how we would implement it ...
pasolo, 'deprecated' means that you shouldn't use a function or technique cause further versions may not support the feature and fail.

the header protections with preprocessor statements is standard C++ and standard C and therefore cannot be deprecated (and i doubt that you can bring evidence that ms named it that way). that means it will always work also in future versions of vc.

your suggestion only works with ms compilers and you shouldn't use it if you ever want to program on other platforms.

Sara
It's hard to say which way is the best to implement this. I for myself don't like to implement something in a class (or struct, which is mostly the same as a class) if this class doesn't have any members and only class-global (static) functions. In this case I decide to implement this globally but within a namespace. There's not much difference between the implementation and IMO none has dis-/atvantages. For example I would implement what sarabande posted like this:

// functions.h

namespace Vdata
{
    extern std::vector < struct Data > vData;
};

// functions.cpp

 ...
 std::vector < struct Data > Vdata::vData;


then everyone can use the vector by including functions.h and like

Vdata::vData.push_back(data);


but I guess that's mostly a matter of ones gusto :o)
Sara...I think I get a vague sense of what you just did there..making it accessible by taking my vector and putting it in a struct again.  This added layer is tasking my brain's ability to keep track of what's going on but I do see what you did there...Given how I am just doing really, really simple things with my first application I want to simplify as much as possible and not have to keep track of these "twists".

Zoppo...my final goal is to read some numbers and apply a series of calculations to them and have it output to my dialog.  Nothing fancy.  This is my first dialog based app and I would like to proceed accordingly. While I see how you experienced programmers are coming up with solutions, I would like to restrict the solutions to those that would be done by a student teaching himself VC++ from a book.

As such, I would like to learn how to re-write my previous program using classes.  This will be a good exercise for me and I will post a new question.  THANK YOU ALL FOR YOUR CONTRIBUTIONS! Each new post is a new concept that adds to my growth and learning.  I really do appreciate it!
Btw, Sara I did not mean to sound dismissive of your solution in my last post.  What I should have said was first, Thank you. And second, I am too noob to fully understand and utilize it yet, and would like to keep things as simple as possible.  Soon,  I will post another question regarding classes.  Thanks again!
i think you should think about whether functions.h should provide a vector at all.

functions.h will - if the name is well-chosen - provide a number of functions. in my opinion that concept doesn't need a global array of elements of a structure.

Sara

@shaolinfunk: That's great! In fact I think EE is a wonderful place for both begginers and professionals to learn a lot and I appreciate it very much if someone says 'I like to learn how to do something' instead of 'give me a solution, no matter if I understand it'.

BTW, maybe you didn't yet see the articles zone. For beginners there are some interesting articles too, especially for starting dialog programming with MFC I would suggest you should take a look at https://www.experts-exchange.com/Programming/System/Windows__Programming/MFC/A_3707-Sudoku-a-complete-MFC-application-Part-1.html - it's much to read but contains a lot of interesting and essential information.

Further maybe you can find interesting sites in the web with google when search for 'tutorial MFC dialog'.
Here is the link to my new question:

https://www.experts-exchange.com/questions/26860757/How-do-I-make-my-app-calculate-1-1-in-Function-cpp-and-then-display-the-result-using-classes.html


Sara,

I am going to have a set a numbers (array of structs) that I need all of my upcoming functions to have access.  Making it global seems the easiest way to do it...is there a better way?
Zoppo, Thanks for that Sudoku link...I am reading it now.