Accessing const global variables from functions

May 24, 2008 at 11:55am
Please, before anyone says, "DONT USE GLOBALS BECAUSE...", I know their bad! Our instructors have already lectured us on never to use globals, unless their constant, this one is.

Okay, onto the actual code. I have a global const int COMMAND_COUNT = 3;, and I want to access it from one of my .h files, but when i try it says C:\...\validate.h `COMMAND_COUNT' was not declared in this scope . To my knowledge, scope was bypassed for globals, am I wrong, or did I miss something?

My main file:
1
2
3
4
5
6
7
8
9
10
11
12
13
/*12mainApp.cpp
holds filenames
calls functions
holds arrays*/

#include "validate.h"

const int COMMAND_COUNT = 3;

int main( int argc, char *argv[] )
{
    ...
}


my .h:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/*validate.h*/

#include ....

class validate
{
    public:
        ....

    private:
        const static int ARG_COUNT = 7;
        string commands[ARG_COUNT];
        string commandList[COMMAND_COUNT];
        int switchCount[COMMAND_COUNT];
};


I saw something about an 'extern' command, but couldn't gather enough info on it to be useful.

Any help would be appreciated, thanks!
May 24, 2008 at 3:29pm
validate.h cannot see COMMAND_COUNT because validate.h does not #include "12mainApp.cpp".

I suggest moving your COMMAND_COUNT global to your validate.h file. That way your 12mainApp.cpp file will see it globally as well.
May 24, 2008 at 6:04pm
closed account (z05DSL3A)
Read up on the extern keyword.

This extern keyword is used to specify that the variable is declared in a different file. This is mostly used to declare variables of global scope in C++ projects.
May 24, 2008 at 10:27pm
Globals are often very useful, and at times unavoidable.
See what the C++FAQ-Lite has to say about "always/never" rules.

http://www.parashift.com/c++-faq-lite/big-picture.html#faq-6.16

(You may first want to read http://www.parashift.com/c++-faq-lite/big-picture.html#faq-6.15)
Last edited on May 24, 2008 at 10:27pm
May 25, 2008 at 2:20am
Okay, I moved it to validate.h and it works just fine! (thanks robo!)

Grey: As i said, I did see something about an extern, however i couldn't find anything to help me use it. any recommended pages for a good example of externs usage?

duoas: yea, thats what i thought. just when i asked a few friends about it they had a go at me for using globals, so I figured I'd point that out first. thanks tho!
May 25, 2008 at 6:13am
@kaeota:
before anyone says, "DONT USE GLOBALS BECAUSE..."

There's nothing wrong with global constants. You shouldn't confuse constants with variables. You should try to avoid using global variables.

@Robo:
I suggest moving your COMMAND_COUNT global to your validate.h file

That's right! The other option is to move it to a new file, called e.g. definitions.h, and include this in both files.

@Grey Wolf:
Read up on the extern keyword

The extern keyword is for variables, not constants.

The reason you need it for variables, is that if you declare int foo in a header file, and include it in two compilation units (which basically means two cpp files), it won't link because of "duplicate reference to foo". The way around this is to declare extern int foo in a header file, and int foo in one of the cpp files. This way the variable can be accessed from anywhere.

On the other hand, constants doesn't cause this problem. You can declare const int FOO = 10 in a header file, and include it everywhere. When the compiler sees the constant in an expression, it inserts the value "inline" instead of a reference to a memory location where it is stored.

More technically: When using constants the compiler doesn't need to create labels in the object file, like it must for variables. The extern keyword means that there is some value in another compilation unit stored in a location labeled by the name. This is of course different from how constants are supposed to be used. Like I said, you should never declare something extern const ....

EDIT:
With "you should never", I really mean that you shouldn't use it in this and similar contexts. There are contexts where it might be useful: If the data type has a complex constructor, or internal state (i.e. if it's not a built-in type), or if the value of the constant is "unknown" or implementation specific -- not available in the header file.
Last edited on May 25, 2008 at 6:22am
May 25, 2008 at 6:25pm
closed account (z05DSL3A)
Ropez,
The OP said
I saw something about an 'extern' command, but couldn't gather enough info on it to be useful.

My suggestion to read up on the extern keyword was for the OPs benefit to learn more about it; I was going to post a link but could not find a single source that would have all the relevant info.

As I said in my post
This extern keyword is used to specify that the variable is declared in a different file. This is mostly used to declare variables of global scope in C++ projects.

I realise that this does not express the intended meaning with due clarity, for this I apologise.

By default consts have internal linkage; this can lead to confusion if say you define the same global variable in different computational units.
file1.cpp
 
const int aConst = 1234;


file2.cpp
 
const int aConst = 5678;


A const can be given external linkage by an explicit declaration:
File1.cpp
1
2
3
...
extern const int a =1234;
...


file2.cpp
1
2
3
4
5
6
7
...
extern const int a;

void func
{
    cout << a << endl;
}


For consistency, all global consts should be placed in header files only.
Last edited on May 25, 2008 at 6:26pm
May 25, 2008 at 6:53pm
@ropez
Don't be so arrogant.

I suggest you read what the C++FAQ-Lite has to say about "always/never" rules:
http://www.parashift.com/c++-faq-lite/big-picture.html#faq-6.16

Putting variable and constant definitions in header files is a disaster waiting to happen. Only put variable and constant declarations in header files. http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=188

The correct way to do it is as follows:
1
2
3
4
5
6
7
8
9
// foo.hpp
#ifndef FOO_HPP
#define FOO_HPP

// Declare stuff that in the foo.o module that other modules may access
extern       int current_foo;
extern const int base_foo;

#endif 

1
2
3
4
5
6
7
8
9
// foo.cpp

#include "foo.hpp"

// constants stored in this module
const int base_foo = 42;

// variables stored in this module
int current_foo = base_foo;


Finally, as you can see from the example, extern is for anything in an 'external context'. For variables and constants, that means that it is found in another module in the project (an object or lib file).

Grey Wolf knows what he is talking about.

[edit] Don't take this too hard. I still like you.
Last edited on May 25, 2008 at 6:54pm
May 25, 2008 at 9:07pm
Sorry for being so arrogant.

I suggest you read what the C++FAQ-Lite has to say about "always/never" rules

If you look at point 6.15 (the one just above the one you referred to), there's actually a definition of terms like "evil code" and "never/always". It basically means "something you should avoid most of the time", which was of course the meaning I intended. I added the EDIT section after making the original post, because I realized like you guys that I shouldn't have written it as strict as "you should never".

Putting [...] constant definitions in header files is a disaster waiting to happen

I think you're wrong. I couldn't find anything to back up this statement in the referenced page. The important difference between variables and constants is that constants have internal linkage by default (thank you, Gray Wolf, I didn't remember the term). Thus, you can indeed put constant definitions in header files without causing troubles. Putting definitions in source files may cause problems like the one that Gray Wolf points out, where constants have the same name, but different values in two source files.

I agree with Gray Wolf's most recent post:
For consistency, all global consts should be placed in header files only.


I agree that my post could have been better formulated, but indeed it brought up an important issue that was until then not mentioned in this thread. There's a difference with global constants and global variables, that affects how they are declared and defined. Since the OP's example actually was about a constant, I thought it should be brought up.
May 25, 2008 at 9:31pm
It looks like I was a little off-the-cuff too. Sorry.

But I still think that you ought not reserve space for the same value more than once...
(I wonder how smart the linker is...)
Topic archived. No new replies allowed.