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.
基本上,我在类A中声明并定义了一个extern变量foo,并在类B和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.
我当前的错误是“为foo指定的存储类”。但是,我想知道这是否是正确的方法。我应该使用静态变量吗?任何帮助都非常感激,因为我已经在这至少一个小时了。
8 个解决方案
#1
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:
在A.h你真的在实际的A级中获得了extern声明吗?你的问题目前用文字说明,但是你的代码片段表明它是在文件级别。我可以得到你所说的错误的唯一方法,即“为foo指定的存储类”,这是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
编辑:看看你自己的答案我认为这就是你所做的。您想要用静态替换extern,然后在A.cpp中用类似的行定义静态
std::string A::foo;
You can then subsequently access it in other places as A::foo
eg.
然后,您可以随后在其他位置访问它,例如A :: foo。
std::cout << A::foo;
#2
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:
如果是这样,你需要在它之前放置std ::
#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.
注意,请确保在头文件中不使用任何using指令(使用命名空间std或使用std :: string),因为这会强制每个起诉你的头文件的人都这样做,这是不好的做法。
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++:
你确定吗?我刚试过这个,它在VC ++和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.
试试看,看看它是否有效。
#3
Do it on file level. Outside main()
在文件级别上执行。外主()
string foo;
int main() {
int main(){
}
Otherwise it is not global at all, but rather "auto"
否则它根本不是全球性的,而是“自动”
#4
While EFraim's answer is correct your other question is, whether this is the correct approach. Answer: No, in most cases.
虽然EFraim的答案是正确的,但另一个问题是,这是否是正确的方法。答:不,在大多数情况下。
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.
拥有一个由多个类操纵的单个全局值只是乞求问题:使用extern非常微妙。任何程序员都没有明确的提示来查看定义变量的代码。他/她必须进行完整的源扫描才能找到它。此外,很难确定何时类更改应用程序控制流中的值,全局变量将不同的类与不可见的带绑定在一起。一个好的设计使类之间的协作显而易见。
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.
更好:让你的全球成为单身人士。这样,您至少可以知道值的定义位置,并且可以通过访问方法控制对值的更改。更好的是:弄清楚为什么类必须能够访问相同的值,找出哪个类完全依赖于哪个方面并相应地修改你的设计。使用extern通常足以解决更深层次的设计问题。
#5
Well, tt looks like C++ doesn't let you use "extern" on anything but objects or functions:
好吧,看起来C ++不允许你在除了对象或函数之外的任何东西上使用“extern”:
"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."
“C ++将extern存储类说明符的使用限制为对象或函数的名称。使用带有类型声明的extern说明符是非法的.extern声明不能出现在类范围中。”
Back to the drawing board...
回到绘图板...
#6
GMan's answer is correct: without including string, you are attempting to instantiate an undefined type, thus the error.
GMan的答案是正确的:没有包含字符串,你试图实例化一个未定义的类型,因此错误。
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.
从标准引用的东西不合适:Jack没有尝试将类型定义为静态,他试图实例化一个对象。
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!
为什么我的所有代码都会在这个BBS中被破坏?上周提出了一个关于C指针的答案,当我想要单个时,我最后得到了双星号!
#7
Other than moving the definition outside of main, make sure you are including the string header before your extern declaration:
除了将定义移到main之外,请确保在extern声明之前包含字符串标题:
#include <string>
#8
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.
在定义foo时,您在函数main中定义了一个局部变量。当你链接时,你会得到一个丢失的符号,因为你的外部foo;永远不会创造。你需要在函数外定义foo。
b.cpp
string foo;
int main () {
foo = "abc";
}
Better yet, you should try a singleton.
更好的是,你应该尝试一个单身人士。
#1
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:
在A.h你真的在实际的A级中获得了extern声明吗?你的问题目前用文字说明,但是你的代码片段表明它是在文件级别。我可以得到你所说的错误的唯一方法,即“为foo指定的存储类”,这是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
编辑:看看你自己的答案我认为这就是你所做的。您想要用静态替换extern,然后在A.cpp中用类似的行定义静态
std::string A::foo;
You can then subsequently access it in other places as A::foo
eg.
然后,您可以随后在其他位置访问它,例如A :: foo。
std::cout << A::foo;
#2
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:
如果是这样,你需要在它之前放置std ::
#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.
注意,请确保在头文件中不使用任何using指令(使用命名空间std或使用std :: string),因为这会强制每个起诉你的头文件的人都这样做,这是不好的做法。
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++:
你确定吗?我刚试过这个,它在VC ++和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.
试试看,看看它是否有效。
#3
Do it on file level. Outside main()
在文件级别上执行。外主()
string foo;
int main() {
int main(){
}
Otherwise it is not global at all, but rather "auto"
否则它根本不是全球性的,而是“自动”
#4
While EFraim's answer is correct your other question is, whether this is the correct approach. Answer: No, in most cases.
虽然EFraim的答案是正确的,但另一个问题是,这是否是正确的方法。答:不,在大多数情况下。
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.
拥有一个由多个类操纵的单个全局值只是乞求问题:使用extern非常微妙。任何程序员都没有明确的提示来查看定义变量的代码。他/她必须进行完整的源扫描才能找到它。此外,很难确定何时类更改应用程序控制流中的值,全局变量将不同的类与不可见的带绑定在一起。一个好的设计使类之间的协作显而易见。
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.
更好:让你的全球成为单身人士。这样,您至少可以知道值的定义位置,并且可以通过访问方法控制对值的更改。更好的是:弄清楚为什么类必须能够访问相同的值,找出哪个类完全依赖于哪个方面并相应地修改你的设计。使用extern通常足以解决更深层次的设计问题。
#5
Well, tt looks like C++ doesn't let you use "extern" on anything but objects or functions:
好吧,看起来C ++不允许你在除了对象或函数之外的任何东西上使用“extern”:
"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."
“C ++将extern存储类说明符的使用限制为对象或函数的名称。使用带有类型声明的extern说明符是非法的.extern声明不能出现在类范围中。”
Back to the drawing board...
回到绘图板...
#6
GMan's answer is correct: without including string, you are attempting to instantiate an undefined type, thus the error.
GMan的答案是正确的:没有包含字符串,你试图实例化一个未定义的类型,因此错误。
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.
从标准引用的东西不合适:Jack没有尝试将类型定义为静态,他试图实例化一个对象。
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!
为什么我的所有代码都会在这个BBS中被破坏?上周提出了一个关于C指针的答案,当我想要单个时,我最后得到了双星号!
#7
Other than moving the definition outside of main, make sure you are including the string header before your extern declaration:
除了将定义移到main之外,请确保在extern声明之前包含字符串标题:
#include <string>
#8
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.
在定义foo时,您在函数main中定义了一个局部变量。当你链接时,你会得到一个丢失的符号,因为你的外部foo;永远不会创造。你需要在函数外定义foo。
b.cpp
string foo;
int main () {
foo = "abc";
}
Better yet, you should try a singleton.
更好的是,你应该尝试一个单身人士。