External Linkage in c++ - c++

I'm making a simple program dealing with poker hands and probabilities. I'm running test cases on various hands, and in my program I need a deck from which to draw my hand that is constant and global. My program has three main objects: Card, Hand, and Deck. I am trying to create a global deck but it seems no matter what I do I get an error saying globalDeck is undefined in hand.cpp. Here is the relevant code:
hand.cpp:
Hand::Hand(int &one, int &two, int &three, int &four, int &five)
{
cardsinHand.push_back(globalDeck.copy(one));
cardsinHand.push_back(globalDeck.copy(two));
cardsinHand.push_back(globalDeck.copy(three));
cardsinHand.push_back(globalDeck.copy(four));
cardsinHand.push_back(globalDeck.copy(five));
}
and my cardgames.cpp file:
#include "stdafx.h"
#include<iostream>
#include "hand.h"
using namespace std;
Deck globalDeck;
void printresults(long successes, long trials)
......
Note: I have tried replacing Deck globalDeck with extern Deck globalDeck, extern const globalDeck, etc etc. Nothing seems to make it so that globalDeck is defined in hand.cpp. Also, the deck will stay constant throughout the program, so it could be declared as a global constant, or a global variable, whichever is easier. My error output is:
1>c:\users\\desktop\semesters past\winter 2013\computer programming\projects\cardgames\cardgames\hand.cpp(31): error C2065: 'globalDeck' : undeclared identifier
1>c:\users\\desktop\semesters past\winter 2013\computer programming\projects\cardgames\cardgames\hand.cpp(31): error C2228: left of '.copy' must have class/struct/union
1> type is 'unknown-type'

Declare your global variable in one header file
extern Deck globalDeck;
and define it in cardgames.cpp
Deck globalDeck;
Explanation:The compiler has to see what globalDeck is before you can use it. And the compiler mostly processes each *.cpp individually, without looking at others. In header files you can say what things are in the program without giving the complete and unique definition.

The global variable globalDeck needs to be declared in every compilation unit (.cpp file) that uses it. It needs to be defined in exactly one compilation unit.
A declaration of the form
Deck globalDeck;
is both a declaration and a definition. A declaration with extern like:
extern Deck globalDeck;
is just a declaration and not a definition.
Header files (.h files) are just text that is included in other files with #include. So you can put the declaration extern Decl globalDeck; in a header file (any header file) and #include that header file in every .cpp file. You will also need the definition in exactly one .cpp file.

class Deck has not been defined in hand.cpp because a header is missing. You need to add something like #include "hand.h" or #include "deck.h".

Related

Instant object initialization in C++ fails with LNK2005 error

These are the errors that I've been receiving:
LNK2005 "class Sally TestObject" (?TestObject##3VSally##A) already defined in Source.obj Project2 c:\Users\W8User\documents\visual studio 2015\Projects\Project2\Project2\Source1.obj
and
LNK1169 one or more multiply defined symbols found Project2 c:\users\w8user\documents\visual studio 2015\Projects\Project2\Debug\Project2.exe
I don't really understand where are these errors coming from. I've tried searching in other SO threads or on the connected Microsoft's website, but none helped.
These are my files:
Source.cpp
#include <iostream>
#include "Header.h"
int main() {
std::cout << TestObject.ReturnTruth();
return 0;
}
Header.h
#pragma once
class Sally
{
public:
bool ReturnTruth();
} TestObject;
Source1.cpp
#include "Header.h"
bool Sally::ReturnTruth()
{
return 1;
}
What I know is that it's enough to move the object initialization into the Source.cpp file and not do it instantly in the header file, but since the instant initialization is a possibility then why wouldn't I use it?
Let's suppose that you have two different .cpp files that each include your Header.h header. Then, each one of those .cpp files gets this code incorporated into it:
class Sally
{
public:
bool ReturnTruth();
} TestObject;
As a result, each file contains the definition of an object named TestObject of type Sally. This breaks the one-definition rule, since there's only supposed to be at most one definition of each object across all translation units, and it's manifesting in your linker error.
If you do want to declare a global object of type Sally, change the header to declare an extern object of type Sally, like this:
class Sally
{
public:
bool ReturnTruth();
};
extern Sally TestObject;
This is a declaration, not a definition, and it's okay to have redundant declarations of objects.
Then, pick a .cpp file - probably the one where you implement the Sally member functions - and add this line:
Sally TestObject;
That puts the definition of the object in a single place, and so fixes the one-definition-rule issue and the linker issue.
Every single place you #include "Header.h" you will have an instance of TestObject, and unless your compiler can fold all of these into a singleton you're going to have several independent, unrelated instances.
That error is advising you that you've made a mistake. One way to fix this is to define in the header file:
extern Sally TestObject;
Which makes it explicitly clear that this will be instantiated elsewhere. Then make an explicit instance in Source1.cpp:
Sally TestObject;
Then your main file will know where to look for this thing.
It's not clear if you want a singleton in the first place. Why can't you just instantiate one inside of main and use it?
As a note, please, please take the time to give your source files meaningful names.
By appending identifier TestObject directly after the class definition Sally, you define a variable in your header file. So if different translation units include this header file, a variable with the same name is defined twice, leading to a linker error. You can resolve this by just declaring the variable, i.e. using extern-keyword in the headerfile, whereas defining the variable then in exactly one .cpp-file:
So write:
Header.h
class Sally
{
public:
bool ReturnTruth();
};
extern Sally TestObject;
Source1.cpp
#include "header.h"
Sally TestObject;
...
in all other CPP-files:
#include "header.h"
...

creating global variables causes linker error

I have an MFC application AVT_testapp, and in the header file (AVT_testappDlg.h) I am trying to create a variable outside of all functions, classes, etc. in order to make it global. Whenever I try to do this though (say I try int x = 7), I get the error:
1>AVT_testappDlg.obj : error LNK2005: "int x" (?x##3HA) already defined in
AVT_testapp.obj
1>..\..\bin\x64\Debug\AVT_testapp.exe : fatal error LNK1169: one or more
multiply defined symbols found
Everything I have found on google says "just add header guards". AVT_testappDlg has 6 #include's, and each of them has header guards.
What else could be causing these errors when creating global variables?
EDIT: Here is the beginning of my header file,
#pragma once
#include "../../src/CoreUtils/nierr.h"
#include "..\..\src\CoreUtils\StringHelpers.h" //includes windows.h
#include "afxwin.h"
#include "afxcmn.h"
#include "IFrameObserver.h"
#include "c:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Include\GdiPlusHeaders.h"
//#include <fstream>
//#include <windows.h>
int x = 7;
using namespace AVT::VmbAPI;
//////////////////////////////////////////////////////////////////////////
////////// MyObserver class ///////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
class MyObserver : public IFrameObserver
{
private:
MyObserver( MyObserver& );
MyObserver& operator=( const MyObserver& );
public:
VmbUchar_t* imageData;
//...
//...
//...
//...
//that's the end of the relevant stuff
You cannot define variables at namespace level in a header. In general it is best not to have global variables, but if you need to you should provide only a declaration in the header and the definition in a single .cpp:
//header
extern int i;
//cpp
int i;
The problem with your code is not related to header guards. Header guards ensure that a header is parsed only once in each translation unit. Lack of header guards causes compiler errors, where the compiler sees, say for example a class, defined multiple times in the same translation unit after preprocessing. In your case the error is a linker error LNK2005, and it means that the same symbol was defined in multiple translation units (in your case in each translation unit that includes the header with the definition).
If the global variable is not const(*), you cannot put it in a header file and include it in multiple translation units (i.e. .cpp files). Otherwise, you will end up with multiple definitions of the same symbol in your program, violating the ODR (One Definition Rule, see Paragraph 3.2 of the C++11 Standard), and the linker will complain about that.
You should use the extern modifier in your shared header to provide only a declaration of your variable:
extern int var;
Then, in one single .cpp file, you can provide a definition for it:
int var;
(*) const global variables have internal linkage by default, so each translation unit will end up having a private copy of it and no multiple definition will occur.
if you insist on having a global variable at least put it in a namespace to avoid collisions with other modules
namespace globals
{
extern int x;
}
then in the .cpp file define it.
int globals::x = 0;
it also makes it more clear that it is a global variable.

C++ variable shared by 2 files

I have 4 files:
shared.h
main.cpp
something.h
something.cpp
shared.h:
#ifndef SHARED_H
#define SHARED_H
int* sth;
#endif
something.h:
#ifndef SOMETHING_H
#define SOMETHING_H
class foo
{
public:
void printVar();
};
#endif
something.cpp:
#include <iostream>
#include "something.h"
#include "shared.h"
using namespace std;
void foo::printVar()
{
cout<<"Foo: "<<*sth<<endl;
};
main.cpp:
#include <cstdlib>
#include <iostream>
#include "shared.h"
#include "something.h"
using namespace std;
int main(int argc, char *argv[])
{
sth=new int(32);
foo x;
cout<<"Main: "<<*sth<<endl;
x.printVar();
system("PAUSE");
return EXIT_SUCCESS;
}
Compiler returns multipe definition of *sth;
I added static modifier to the *sth and it compiles, but crashes. I changed the printings to print the adresses of pointer and I had program returned:
Main: 0x3e0f20
Foo: 0
Why is the foo's pointer not assigned? I want to assign it only once in main and then share in other files... How can I do this? Is it something with extern modifier?
Thanx for any replies.
In shared.h you want to say:
extern int* sth;
to promise the compiler that sth exists somewhere.
Then in one (and only one) of the .cpp files you need to write:
int* sth;
To make it actually exists. In general you probably want to read about the difference between declaration and definition. As a rule of thumb you only want to declare things in header files, not define them.
When you wrote static previously you said that a variable with the same name exists in every file, but is "local" to each, i.e. the sth in main.cpp won't be the same as the sth in something.cpp.
Yes, use extern. Put extern int* sth; in the header, and then in one of the source files put int* sth;.
extern tells the compiler and linker that the actual variable/function definition is in another compilation unit (i.e. another source file).
You need to mark sth as extern in the header to make it a declaration, and provide a definition for it in one of the cpp files. Otherwise, the variable is declared in each compilation unit where the header is included, which is not the effect you are looking for.
P.S. I assume that you know why global variables are not good, right?
"I have 4 files".
Let me stop you right there. I agree that you have four files, but that's not really relevant. You have two translation units. A translation unit is the quantum of text that is fed into your compiler. Your translation units, let's call them MAIN and SOMETHING, consist of the result of preprocessing your files main.cpp and something.cpp, respectively.
After preprocessing, each of your translation units includes a line int *sth; This line declares and defines the variable sth.
The one-definition-rule requires that you have, in your entire program, exactly one (not more, not fewer) definition of sth. In order to accomplish this, you must have exactly one source-code line int *sth; in exactly one translation unit, and as many extern int *sth; as you require.
In your case, I would put int *sth; in MAIN and extern int *sth; in SOMETHING. Additionally, you can have as many extra copies of extern int *sth; as you feel like -- they won't hurt anything.
Now, back to your four files. You should put extern int *sth; in shared.h. This means that MAIN and SOMETHING will both have an extern line in them. You should also put int *sth; in main.cpp, so that MAIN will have the definition.
And there you are: MAIN and SOMETHING both have extern lines, so they are both referring to the same variable. MAIN also has a definition. so the sth variable has exactly one of those.
Aside: Why does static int *sth; in shared.h do the wrong thing?
Because each of the two translation units see their own static declaration. A static declaration reduces the linkage of the declared name to that single translation unit.
You don't want to make it a static global as that will create a local sth in every translation unit and you are only allocating it in one. This is why it crashed in Foo::printVar as in that scope it was an uninitialized pointer.
You want to declare it as extern int* sth; in the shared header then put int* sth; before main or in at least one place before it's used.
Actually, if you really need a globally accessible object, allocated on the heap, and you want to share it then it may be better as extern std::shared_ptr<int> sth;. Define it as std::shared_ptr<int> sth; the same way in one of the CPP files and call std::make_shared to allocate it. This way deallocating the memory will be handled automatically when the last object that uses it goes out of scope.

Issue declaring extern class object

Let me start by saying I've extensively searched for answers on google and more specifically here.
The thing is I actually (at least I think I did) found people with similar problems, though the answer given to them gave me another problem.
I'm using Visual Studio 2010 Express and working with SFML libary (though i do not think this last part is relevant)
So here it goes:
I have a source file called player.cpp which holds class Player and I have a header file (included in all source files) called cc.h(command and control) that holds all the necessary includes and external variables/functions. The essential code can be summed up in the following:
Player.cpp:
#include "cc.h"
class Player
{
private:
//some variables here
public:
//more variables and some functions
}john;//example instance
cc.h:
#pragma once
//some #includes
//some externs
extern Player john;
Now in cc.h the word Player is underlined as a mistake saying it is an undefined identifier , but only sometimes, other times visual studio doesn't mark it as a mistake, instead it recognizes it as a class but doesn't recognize john as an object/instance (i hope it's called this way) of that same class.
Furthermore, at compiling the first error it shows is "error C2146: syntax error : missing ';' before identifier 'john'" at the line of the extern declaration of john, in cc.h, which apparently (to me) does not make any sense.
The global declaration in cc.h would not help you, I guess - because you declare it to access it from else where (other than Player.cpp), but for this you need the method signatures - a soon as you want to access john from elsewhere and thus include Player.cpp, you get duplicates symbols.
Please consider creating a Player.h file where only the class and method signatures are declared - like this:
#ifndef PLAYER_H_
#define PLAYER_H_
class Player
{
void doSomething();
};
#endif
and add this to cc.h:
#include <Player.h>
extern Player john;
and in your Player.cpp
#include <Player.h>
Player john;
void Player::doSomething()
{
//...
}
This makes sure that the Player signatures are known and a valid instance is declared globally.
You need to put the definition of your Player class in the header file, before you declare the extern variable. Otherwise the compiler has no idea what Player is.
I suggest something like this:
player.h
#ifndef PLAYER_H_
#define PLAYER_H_
class Player {
...
};
#endif
player.cpp
#include "player.h"
Player john;
cc.h
#ifndef CC_H_
#define CC_H_
#include "player.h"
extern Player john;
#endif
You need to define the Player class, in your header file
Use extern to use variable that has an external linkage, and is already defined in some other file.
For example: you have file a.cpp, and inside this file has a global variable Player p. If you want to use the same exact instance p of Player in file c.cpp, then inside file c.cpp you write extern Player p.
I hope i made myself clear.
"extern Player john;" is considered to be undefined identifier as the compiler is unable to understand what Player is, as you have not included the file Player.cpp where the class Player is declared to cc.h .
It is always recommended to declare the class and its methods in header files say for example in Player.h and then define these methods in the source file i.e Player.cpp.
And to include Player.h in your cc.h so that compiler understands where " Player john;" is declared.

Can I include global static member?

There are few global variables which are static in one of the header files. I see these variables are used in the associated .cc files. So, looks like this has no issues.
My questions are:
Whats the difference between including a global variable vs static global variable ?
I know static global doesnt have visibility outside its file. But dont know how this would work when it comes as part of a .h which is #included.
I wrote a sample program, and tried the same thing. But, I get compilation error the moment I make the variable static. When it is just global, it is fine.
So, is there something which I am missing on a regular g++ build ? (Please note, the initial case was on our official code base which has enough makefiles, .h files and all).
Thanks for the help !
Here is my sample program :
.h file:
#include <iostream>
typedef unsigned int uint;
static const int appk=189;
class abc1
{
public:
abc1(int x);
virtual void printVal();
};
.cc file:
#include "abc1.h"
extern int appk;
abc1::abc1(int x)
{
}
void abc1::printVal()
{
printf("abc1 print: %d\n", appk);
}
(1) If you put a global variable in a .h file and include it in various .cpp/.cc files then it will be defined multiple times for every file. So you are most like to get a linker error.
To overcome that, mostly you are likely to use extern keyword:
// myfile.h
extern int i;
and define that in only one translation unit:
// somefile.cc
int i;
(2) If you put a static global in a .h file and include it, then you will not get any error, because for every different translation unit, there will be a different copy for that static global variable.
// myfile.h
static int i; // creates a unique and unrelated copy in all .cc file where included
However, such usage is deprecated; instead of that it's better to use unnamed namespace:
namespace {
int i;
}
From your question, I don't see that you should get any linker error for static global.
Hard to tell your compilation error without code, but if you have a header that declares a static global, then you just create that global variable independently and separately in each translation unit that includes the header.
Example:
header.h:
#ifndef H_XXX
#define H_XXX
static int a;
#endif
file1.cpp:
#include "header.h"
// now have access to a variable called "a"
file2.cpp:
#include "header.h"
// now also have access to some "a"
The two files both have access to a global variable called a, but each file has its own separate copy, private to its translation unit, which is not visible outside.
For a practical example, I think cout is declared as a static global, so everyone who uses <iostream> gets their own copy.
static variable has internal-linkage. What it means is that if you have a static variable a in x.h and you include x.h in two files say m.cpp and n.pp then each of these two files gets its own copy of a which means if you change its value in m.cpp, then n.cpp is not going to see that change, because there exists two variables with same name in each translation unit (.cpp). And they're independent of each other.
But if a is not static, then including x.h in more than one files, you will get multiple-definition error, because each inclusion of x.h will try to define a, but since a is not static; it has external linkage now, which means if its defined in m.cpp, then you will get error when including x.h in n.cpp (or vice-versa). In this case, you've to write x.h as:
//x.h
extern int a;
And then define a in exactly one .cpp file, either m.cpp or n.cpp, but not both. Say its m.cpp.
//m.cpp
#include "x.h"
int a =10;
And you're done. Now you can include x.h in as many .cpp file as you want, and can access a, modify its value, do whatever you want. Any change to it, will be seen by all .cpp files now.