Jack BeNimble
Jack BeNimble

Reputation: 36663

How to construct a static global variable in C++

I'm having some trouble compiling/linking a set of classes, several of them dealing with a common global variable.

Basically, I declare and define a extern variable foo in class A and access/update it in classes B and C.

The relevant code looks like this:

A.h

extern string foo; // declare it <=== compiler error "storage class specified for foo"

B.cpp

include A.h  
string foo; // define it  

main () {   
...  
foo = "abc";      
}  

C.cpp

include A.h  
cout << foo; // print it  

My current error is "storage class specified for foo". But, I'm wondering if this is the correct approach. Should I be using a static variable? Any help much appreciated, as I've been on this for at least an hour by now.

Upvotes: 0

Views: 5405

Answers (8)

Troubadour
Troubadour

Reputation: 13421

In A.h have you actually got the extern declaration within the actual class A? Your question currently says this in words but then your code snippet suggests it is at file level. The only way I can get the error you are talking about i.e. "storage class specified for foo" is for the following in A.h:

class A
{
public:
    extern std::string foo;
};

Perhaps this is your problem?

Edit: Looking at your own answer I think this is what you've done. You want to replace extern with static and then define that static in A.cpp with a line like

std::string A::foo;

You can then subsequently access it in other places as A::foo eg.

std::cout << A::foo;

Upvotes: 2

GManNickG
GManNickG

Reputation: 503865

Since your error is on the extern, I'm guessing it doesn't know what the type is.

Have you included string?

#include <string>

And if so, you need to put std:: before it:

#include <string>
extern std::string foo;

Side note, make sure you don't use any using directives (using namespace std or using std::string) in your header file, because then you force everyone who sues your header file to do the same, which is bad practice.

Edit

...but that's how I have it coded.

Are you sure? I just tried this and it works completely fine in both VC++ and g++:

A.h

#include <string>

extern std::string foo;

B.cpp

#include "A.h"

std::string foo;

int main (void)
{   
    foo = "abc";      
}

C.cpp

#include "A.h"
#include <iostream>

int some_function(void)
{   
    std::cout << foo << std::endl;
}

Try that out and see if it works.

Upvotes: 6

Jim Buck
Jim Buck

Reputation: 20726

Other than moving the definition outside of main, make sure you are including the string header before your extern declaration:

#include <string>

Upvotes: 1

hoohoo
hoohoo

Reputation:

GMan's answer is correct: without including string, you are attempting to instantiate an undefined type, thus the error.

The stuff quoted from the standard is not apropos: Jack is not attempting to define a type as static, he's trying to instantiate an object.

Yes you can only do stuff like

class foo {
  // ...
  static int hoo; // class variable same in all instances of foo
  // ...
};

...but that's not what jack is doing.

Why does all my code get mangled in this BBS? Last week put up an answer about C pointers and I wound up with double asterix's when I wanted single ones!

Upvotes: 1

Jack BeNimble
Jack BeNimble

Reputation: 36663

Well, tt looks like C++ doesn't let you use "extern" on anything but objects or functions:

from http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=/com.ibm.xlcpp8a.doc/language/ref/extsc.htm

"C++ restricts the use of the extern storage class specifier to the names of objects or functions. Using the extern specifier with type declarations is illegal. An extern declaration cannot appear in class scope."

Back to the drawing board...

Upvotes: 1

haffax
haffax

Reputation: 6008

While EFraim's answer is correct your other question is, whether this is the correct approach. Answer: No, in most cases.

Having a single global value that is manipulated by multiple classes is just begging for problems: Using extern is pretty subtle. There are no clear hints for any programmer looking at your code where the variable is defined. He/she has to do a full source scan to find it. Also it is difficult to determine when what class changes the value in the control flow of your application, a global variable ties different classes together with an invisible band. A good design makes collaborations between classes explicit.

Better: Make your global a singleton. This way you at least know where the value is defined and you can control changes to the value via access methods. Even better: Work out why the classes have to have access to the same value, work out which class depends on what aspect exactly and revise your design accordingly. Often enough using extern is just a quick fix for a deeper design problem.

Upvotes: 2

David Nehme
David Nehme

Reputation: 21572

When you are defining foo, you are defining a local variable in the function main. When you link, you will get a missing symbol because your extern foo; is never created. You need to have foo defined outside a function.

b.cpp

string foo;
int main () {
   foo = "abc";
}

Better yet, you should try a singleton.

Upvotes: 0

EFraim
EFraim

Reputation: 13028

Do it on file level. Outside main()

string foo;

int main() {

}

Otherwise it is not global at all, but rather "auto"

Upvotes: 4

Related Questions