Reputation: 36663
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
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
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.
...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++:
#include <string>
extern std::string foo;
#include "A.h"
std::string foo;
int main (void)
{
foo = "abc";
}
#include "A.h"
#include <iostream>
int some_function(void)
{
std::cout << foo << std::endl;
}
Try that out and see if it works.
Upvotes: 6
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
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
Reputation: 36663
Well, tt looks like C++ doesn't let you use "extern" on anything but objects or functions:
"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
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
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
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