我注意到我的一些函数实际上没有访问对象,所以我将它们static
。然后编译器告诉我他们访问的所有变量也必须是静态的 - 到目前为止,这是可以理解的。我有一堆字符串变量,如
string RE_ANY = "([^\\n]*)";
string RE_ANY_RELUCTANT = "([^\\n]*?)";
等课程。然后,我将它们全部static const
,因为它们永远不会改变。但是,如果我将它们移出类,我的程序只会编译:否则,MSVC ++ 2010会抱怨“只有静态常量变量可以在类中初始化”。
那很不幸。有解决方法吗?我想把它们留在他们所属的班级里。
答案 0 :(得分:113)
它们不能在类中初始化,但可以在类文件外部在源文件中初始化:
// inside the class
class Thing {
static string RE_ANY;
static string RE_ANY_RELUCTANT;
};
// in the source file
string Thing::RE_ANY = "([^\\n]*)";
string Thing::RE_ANY_RELUCTANT = "([^\\n]*?)";
<强>更新强>
我刚刚注意到你问题的第一行 - 你不想要制作这些功能static
,你想要制作它们const
。使它们static
意味着它们不再与对象相关联(因此它们不能访问任何非静态成员),并且使数据静态意味着它将与此类型的所有对象共享。这可能不是你想要的。制作const
只是意味着他们无法修改任何成员,但仍然可以访问它们。
答案 1 :(得分:28)
Mike Seymour给了你正确的答案,但要补充......
C ++允许您在类体中声明和定义 static const integral types ,正如编译器所说。所以你实际上可以这样做:
class Foo
{
static const int someInt = 1;
static const short someShort = 2;
// etc.
};
你不能用任何其他类型做到这一点,在这种情况下你应该在你的.cpp文件中定义它们。
答案 2 :(得分:15)
静态成员变量必须在类中声明,然后在其外部定义!
没有解决方法,只需将其实际定义放在源文件中即可。
从你的描述来看,它闻起来就像你没有以正确的方式使用静态变量。如果它们永远不会改变,你应该使用常量变量,但是你的描述过于通用而无法再说些什么。
静态成员变量对于类的任何实例始终保持相同的值:如果更改一个对象的静态变量,它也将对所有其他对象进行更改(实际上,您也可以在没有实例的情况下访问它们)类 - 即:一个对象)。
答案 3 :(得分:15)
从C ++ 11开始,它可以在constexpr
的类中完成。
class stat {
public:
// init inside class
static constexpr double inlineStaticVar = 22;
};
现在可以使用以下方式访问变量:
stat::inlineStaticVar
答案 4 :(得分:9)
我觉得值得补充一点,静态变量与常量变量不同。
在类
中使用常量变量struct Foo{
const int a;
Foo(int b) : a(b){}
}
我们会像这样声明它
fooA = new Foo(5);
fooB = new Foo(10);
// fooA.a = 5;
// fooB.a = 10;
对于静态变量
struct Bar{
static int a;
Foo(int b){
a = b;
}
}
Bar::a = 0; // set value for a
这样使用
barA = new Bar(5);
barB = new Bar(10);
// barA.a = 10;
// barB.a = 10;
// Bar::a = 10;
你看到这里发生了什么。与Foo的每个实例一起实例化的常量变量,因为Foo被实例化,每个Foo实例都有一个单独的值,并且Foo根本不能更改它。
与Bar一样,无论Bar有多少个实例,它们只是Bar :: a的一个值。它们都共享这个值,您也可以使用它们作为Bar的任何实例来访问它。静态变量也遵守公共/私有规则,因此您可以使只有Bar的实例可以读取Bar :: a的值;
答案 5 :(得分:6)
只是添加其他答案。要初始化复杂的静态成员,您可以按以下方式执行此操作:
像往常一样声明你的静态成员。
// myClass.h
class myClass
{
static complexClass s_complex;
//...
};
创建一个小函数来初始化你的课程,如果这样做并不容易。这只是静态成员初始化的一次。 (请注意,将使用complexClass的复制构造函数,因此应该很好地定义它。)
//class.cpp
#include myClass.h
complexClass initFunction()
{
complexClass c;
c.add(...);
c.compute(...);
c.sort(...);
// Etc.
return c;
}
complexClass myClass::s_complex = initFunction();
答案 6 :(得分:2)
如果您的目标是初始化头文件中的静态变量(而不是* .cpp文件,如果您只坚持使用#34;标题,那么您可能需要该文件),那么您可以通过使用模板解决初始化问题。模板化静态变量可以在标题中初始化,而不会导致定义多个符号。
见这里的例子:
答案 7 :(得分:1)
(可选)将所有常量移动到.cpp文件,而不在.h文件中声明。使用匿名命名空间使它们在cpp模块之外不可见。
// MyClass.cpp
#include "MyClass.h"
// anonymous namespace
namespace
{
string RE_ANY = "([^\\n]*)";
string RE_ANY_RELUCTANT = "([^\\n]*?)";
}
// member function (static or not)
bool MyClass::foo()
{
// logic that uses constants
return RE_ANY_RELUCTANT.size() > 0;
}
答案 8 :(得分:0)
有些答案似乎误导。
.cpp
文件进行初始化,只需在标题文件中执行相同操作。#ifndef CLASS_A_H
#define CLASS_A_H
#include <string>
class A
{
private:
static std::string str;
static int x;
};
// Initialize with no values
std::string A::str;
int A::x;
// Initialize with values
//std::string A::str = "SO!";
//int A::x = 900;
#endif