By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
440,939 Members | 1,602 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 440,939 IT Pros & Developers. It's quick & easy.

best practice for global variables?

P: n/a
Hello,

I'm trying to make sure I use best practices (and hence save myself some
headaches) with the declaration and definition of global variables. Let's
say I have an app with 30 files, including main.cpp I have global
variables that need defining in main.cpp and declaring in all other files
in. The way I've seen it done is to define/declare everything in one header
file (e.g. globalincludes.h) prefaced with the word EXTERN

Then in main.cpp EXTERN is
#define EXTERN

and in all other files EXTERN is
#define EXTERN extern

so everything is extern except in main. However, it still seems like I need
both a definition and declaration. If (in globalincludes.h) I have variable

EXTERN int MonthEndDate[] = {31, 28, 31, 30, 31, 30, 31, 31, 30 ,31, 30,
31};

This works as the definition, but I get multiple redefinitions even with the
extern keyword. Do I need separate declarations too?

extern int MonthEndDate[];

What should my globalincludes.h file look like for this one variable?

Thanks!

Jay

Mar 30 '06 #1
Share this Question
Share on Google+
10 Replies


P: n/a
* Jay Wolfe:

I'm trying to make sure I use best practices (and hence save myself some
headaches) with the declaration and definition of global variables.
The best practice is: don't use global variables.
[snip] What should my globalincludes.h file look like for this one variable?


The best practice is: don't use global include files.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Mar 30 '06 #2

P: n/a

"Alf P. Steinbach" <al***@start.no> wrote in message
news:49************@individual.net...
* Jay Wolfe:

I'm trying to make sure I use best practices (and hence save myself some
headaches) with the declaration and definition of global variables.


The best practice is: don't use global variables.

[snip]
What should my globalincludes.h file look like for this one variable?


The best practice is: don't use global include files.


Thanks, but that's not really very helpful. All you've done is tell me I
can't do something, but offered no explanation why and no alternatives.
Best practice means what is best to do, not all the things you shouldn't do.
I have common data that every file needs to see and global variables seems
like it was made for this. If you have a good solution, please let me know.

Jay
Mar 30 '06 #3

P: n/a

Jay Wolfe wrote:
"Alf P. Steinbach" <al***@start.no> wrote in message
news:49************@individual.net...
* Jay Wolfe:

I'm trying to make sure I use best practices (and hence save myself some
headaches) with the declaration and definition of global variables.


The best practice is: don't use global variables.

[snip]
What should my globalincludes.h file look like for this one variable?


The best practice is: don't use global include files.


Thanks, but that's not really very helpful. All you've done is tell me I
can't do something, but offered no explanation why and no alternatives.
Best practice means what is best to do, not all the things you shouldn't do.
I have common data that every file needs to see and global variables seems
like it was made for this. If you have a good solution, please let me know.


There is always a way to avoid global variables. One such way is a
singleton.

globals like so:

header.h:

extern type var[];

main.cpp
type var[];

Mar 30 '06 #4

P: n/a
Jay Wolfe posted:
Hello,

I'm trying to make sure I use best practices (and hence save myself
some headaches) with the declaration and definition of global
variables. Let's say I have an app with 30 files, including main.cpp
I have global variables that need defining in main.cpp and declaring
in all other files in. The way I've seen it done is to define/declare
everything in one header file (e.g. globalincludes.h) prefaced with
the word EXTERN

Then in main.cpp EXTERN is
#define EXTERN

and in all other files EXTERN is
#define EXTERN extern

so everything is extern except in main. However, it still seems like I
need both a definition and declaration. If (in globalincludes.h) I have
variable

EXTERN int MonthEndDate[] = {31, 28, 31, 30, 31, 30, 31, 31, 30 ,31,
30, 31};

This works as the definition, but I get multiple redefinitions even
with the extern keyword. Do I need separate declarations too?


The default is "extern", so everything is still "extern" even if you leave
the keyword out. Think of how (at function scope):

int a;

is the same as:

int auto a;

Well, as a global variable, it doesn't matter whether you put in "extern" or
not (when dealing with non-const objects). If a global object is const, then
the default changes to "static".

There' two common ways of accomplishing what you want. Firstly, by just
using a header file:

// global_objects.hpp

static int const month_last_day[] = {31, 28, 31, 30, 31, 30, 31, 31, 30 ,31,
30, 31};

There's no need to write "static" above, as it's the default for global
const variables. The downside to this choice is that you have more than one
object called "month_last_day" -- you've got one object for each translation
unit in which it's declared.

Here's the other way, you use a header file and a source file:

//global_objects.hpp

extern int const month_last_day[12];
//global_objects.cpp

extern int const month_last_day[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30
,31, 30, 31};
Now you've only got one object for the entire program.
-Tomás
Mar 30 '06 #5

P: n/a
Jay Wolfe wrote:
Thanks, but that's not really very helpful.
Many people here had to work with legacy codebases that abused globals in
ways that caused and hid bugs. The best tip for them is always "just
don't", so we tend to be a little short. However in your case...
EXTERN int MonthEndDate[] = {31, 28, 31, 30, 31, 30, 31, 31, 30 ,31, 30,
31};


That is a C trick. Because C++ knows that global _constants_ are mostly
harmless, C++ builds the trick into the language - for constants. You can
put this in a header:

static int const MonthEndDate[] = {31, 28, 31, 30, 31, 30, 31, 31, 30 ,31,
30, 31};

Now consider leap years, the precession of the equinoxes, etc. MonthEndDate
isn't _reaaaaally_ constant, so you ought to simply make it a function.

--
Phlip
http://www.greencheese.org/ZeekLand <-- NOT a blog!!!
Mar 30 '06 #6

P: n/a

"Tomás" <NU**@NULL.NULL> wrote in message
news:th******************@news.indigo.ie...

Here's the other way, you use a header file and a source file:

//global_objects.hpp

extern int const month_last_day[12];

//global_objects.cpp

extern int const month_last_day[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30
,31, 30, 31};


Thank you gentlement for your help, It's getting clearer.

In going back to my original question, it seems you do have 2 elements for
each variable: (1) a declaration included in the header file for inclusion
in all files, and (2) the actual definition in a separate cpp file. The
real difference between what I had and what you present here lies with the
use of the word extern.

Naturally I'd like to avoid multiple instances of global constants, so your
second method seems superior, but why, in global_objects.cpp do you again
use 'extern'?

Thanks!
Jay


Mar 30 '06 #7

P: n/a
Jay Wolfe wrote:
In going back to my original question, it seems you do have 2 elements for
each variable: (1) a declaration included in the header file for inclusion
in all files, and (2) the actual definition in a separate cpp file.Â*Â*The
real difference between what I had and what you present here lies with the
use of the word extern.


Please use 'static' in this specific situation. 'static const' generally
means you may define something in only one .h file, and the compiler will
work out all the details. No extern.

--
Phlip
http://www.greencheese.org/ZeekLand <-- NOT a blog!!!
Mar 30 '06 #8

P: n/a
Naturally I'd like to avoid multiple instances of global constants, so
your second method seems superior, but why, in global_objects.cpp do
you again use 'extern'?


I didn't have to, it will still compile if you take it out.

However, the "extern" in the header file is indeed necessary. (I don't know
why... but if I really cared I'd look it up. All I know is that it won't
compile without it.)

Yes, you say that my second way seems superior, but there are times when it
isn't:

// global.hpp

int const monkey = 5;
If you include this in five translation units, then the value can instantly
be subsituted into the code. (So your compiler can turn:

i += monkey;

into:

i += 5;

Which is a good thing!
So basically, use the first method if you have a complicated object, like an
array or a class. Also, any other time when you only want ONE of the object.

Use the second method if you have a simple object, like an "int". Note
however, that in the code I wrote just above, that there's a separate
"monkey" for each translation unit, so you can't use it for something like a
template parameter, as in:

template<int const &n> int Func();

int main()
{
Func<monkey>();
}
To achieve the above behaviour, you need to use the source file/header file
combo.

-Tomás

Mar 30 '06 #9

P: n/a
This is how I'd implement a global array:
// file globalincludes.h

#ifdef DEFINE_GLOBALS
#define EXTERN
#else
#define EXTERN extern
#endif

EXTERN int MonthEndDate[]
#ifdef DEFINE_GLOBALS
= {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
#endif
;
// file global.cpp defines the global

#define DEFINE_GLOBALS
#include "globalincludes.h"
// file main.cpp sees only the declaration

#include <iostream>
#include <ostream>
#include "globalincludes.h"

int main() {
std::cout << "month lengths:\n";
for (int i = 0; i < 12; ++i)
std::cout << MonthEndDate[i] << '\n';
return 0;
}
The solution is inelegant, but it does keep the stuff related to that
variable in one place, and is easily comprehensible to other
programmers. It would be nice to avoid that clumsy business of framing
the initializer with preprocessor directives, but I've never figured
out how.

--
Paul Hirose <jv********@earINVALIDthlink.net>
To reply by email remove INVALID

Apr 1 '06 #10

P: n/a
Paul Hirose wrote:
EXTERN int MonthEndDate[]
#ifdef DEFINE_GLOBALS
= {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
#endif
;


In C.

C++ can just make the line static and constant, and the compiler will take
care of all that for you.

--
Phlip
http://www.greencheese.org/ZeekLand <-- NOT a blog!!!
Apr 1 '06 #11

This discussion thread is closed

Replies have been disabled for this discussion.