PDA

View Full Version : Sharing Global Values in multiple object files


erkokite
10-27-2005, 09:37 PM
Ok, I have 3 files:

test.h:

int b;

void output();


test.cpp:

#include <iostream>

using namespace std;

#include <test.h>


void output(){
cout<<b<<endl;
}



main.cpp:

#include <iostream>

using namespace std;

#include <test.h>

int main()
{
b=2;
output();
return 0;
}


I need to share the value for the variable, b, between main.cpp and test.cpp, so that output() outputs the value 2. Is there any way to do this?

corey
10-27-2005, 10:14 PM
Define int b in test.cpp and then declare it as extern in test.h that is included in main.cpp

corey

Reedbeta
10-27-2005, 11:06 PM
What I like to do is something like this.

globals.h:
#ifndef GLOBALS_H
#define GLOBALS_H

#ifdef DECLARE_GLOBALS
#define GLOBAL
#elif
#define GLOBAL extern
#endif

GLOBAL int foo;
GLOBAL CMyClass bar;
// ...

#endif

Then in main.cpp I do
#define DECLARE_GLOBALS
#include "globals.h"

whereas in other files I just include the globals.h file normally. This lets me use one line of code for each variable (avoids duplicating code) and automatically manages the externs and declarations.

.oisyn
10-28-2005, 01:30 AM
Reedbeta: what if you want to initialize the global objects you're using?

AticAtac
10-28-2005, 04:15 AM
As suggested i would do it this (clean) way:

Test.h:

extern int b;

Test.cpp:

int b = <Init Value>;


Any other files (main.cpp) just include Test.h and everything is ok !

erkokite
10-28-2005, 07:59 AM
Is there a way to use a custom type like this:


struct test{
int a;
};

extern test t1;


I can get single variables to work, but I can't get structs to work. Any ideas?

eddie
10-28-2005, 01:07 PM
That should work.

Something like this:

main.h


struct test
{
int a;
};



main.cpp

#include <iostream>
using namespace std;

extern test t1;

int main(void)
{
cout << "Got: " << t1.a << endl;
return(0);
}



main2.cpp

#include "main.h"

test t1;



Now, that said, a couple of things about style.

I'm not big on global variables personally, but when they are needed, I'm much happier with implementing the Singleton pattern. This pattern will let you control *when* your variable is initialized, which is really important in the cases where you have globals that require use of one another, as well as provide a class-like interface to retrieving and utilizing the variable.

A simple singleton pattern:



class test
{
public:
static test *Get()
{
if(m_pTest == NULL)
{
m_pTest = new test;
}
return m_pTest;
}

void Shutdown()
{
if(m_pTest != NULL)
{
delete m_pTest;
}
}

int GetA() const { return m_A; }
void SetA(const int A) { m_A = A; }

private:
test() {}; // private constructor, so noone else can create
static test *m_pTest; // Static instance of this object.

int m_A;

};



Then in a CPP file you add:


test *test::m_pTest = NULL;


And you're done. :)

You use it by doing the following:



int main(void)
{
test *pTest = test::Get();

pTest->SetA(1);
pTest->GetA();
// etc.

pTest->Shutdown();

return 0;
}



Not sure if that helps or not, but I find it's very useful for larger structures that you want global. (Game-wide state information, rendering layers, etc).

Cheers!

Rydinare
10-28-2005, 11:03 PM
The extern solution mentioned above is the answer to the problem.

However, certainly globals are not neat and cause lots of problems (tough to manage, require a lot of additional consideration if moving to a multithreaded environment, etc...).

You may want to consider putting all of your "globals" inside of a singleton class (there are still better ways to design it, but it would be an improvement), instead. This will allow you more control, as to where you can single out the problem in one class, versus searching all over the codebase for each instance where you have an issue.

Reedbeta
10-29-2005, 12:01 AM
@.oisyn: obviously I can't include initializers with this scheme (unless I were to modify the macro to allow this, which would be ugly), but I find that I usually don't need compile-time initializations for global variables; and the advantage of this scheme, that I don't have to maintain two separate declarations (the extern and the non-extern ones), seems to outweigh this inconvenience at least for me.

Jare
10-29-2005, 05:05 PM
Quick nitpick on Reedbeta's suggestion: "declarations" introduce identifiers to the compiler, whereas "definitions" may actually introduce content in the generated code. I can't remember the exact wording in the C++ standard, but it's along those lines. Thus, the DECLARE_GLOBALS macro would be more appropriately named DEFINE_GLOBALS.

corey
10-29-2005, 05:12 PM
Quick nitpick on Reedbeta's suggestion: "declarations" introduce identifiers to the compiler, whereas "definitions" may actually introduce content in the generated code. I can't remember the exact wording in the C++ standard, but it's along those lines. Thus, the DECLARE_GLOBALS macro would be more appropriately named DEFINE_GLOBALS.
Both are declarations, neither is a definition in that context.

Ah but you meant the use. extern variable is a declaration unless it includes an initializer then it is a definition.

corey

Reedbeta
10-29-2005, 06:46 PM
Actually, I was wondering whether declare or define was the right term in that context =D It sounds weird to me to say "define a variable", though; as far as I can remember, variables are always declared, while functions and classes are defined.

corey
10-29-2005, 08:53 PM
Actually, I was wondering whether declare or define was the right term in that context =D It sounds weird to me to say "define a variable", though; as far as I can remember, variables are always declared, while functions and classes are defined.
An extern variable is declared unless it has an initializer.
Other non-static-class variables are defined with/without initializer.

A function is defined if it includes a body.

A class is defined under similar requirements.

If it will help you understand, I can post the first 2 paragraphs of [basic.def] :

A declaration (clause 7) introduces names into a translation unit or redeclares names introduced by previous
declarations. A declaration specifies the interpretation and attributes of these names.

A declaration is a definition unless it declares a function without specifying the function’s body (8.4), it
contains the extern specifier (7.1.1) or a linkage-specification24) (7.5) and neither an initializer nor a
function-body, it declares a static data member in a class declaration (9.4), it is a class name declaration
(9.1), or it is a typedef declaration (7.1.3), a using-declaration (7.3.3), or a using-directive (7.3.4).

corey

.oisyn
10-31-2005, 01:51 AM
And in code:
void f(); // function declaration
void f() // function definition
{
}


extern int foo; // variable declaration
int foo; // variable definition

class S; // class declaration
class S // class definition
{
void foo(); // member function declaration within a class definition
};

void S::foo() // member function definition, also implementation
{
}