[英]Initialize static variables in C++ class?
我注意到我的一些函數實際上沒有訪問對象,所以我把它們做成了static
。 然后編譯器告訴我他們訪問的所有變量也必須是靜態的 - 到目前為止,這是可以理解的。 我有一堆字符串變量,如
string RE_ANY = "([^\\n]*)";
string RE_ANY_RELUCTANT = "([^\\n]*?)";
在課堂上等等。 然后我把它們都變成了static const
因為它們永遠不會改變。 但是,如果我將它們移出類,我的程序只會編譯:否則,MSVC ++ 2010會抱怨“只有靜態常量變量可以在類中初始化”。
那很不幸。 有解決方法嗎? 我想把它們留在他們所屬的班級里面。
它們不能在類中初始化,但可以在類文件外的源文件中初始化:
// 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
只意味着它們不能修改任何成員,但仍然可以訪問它們。
Mike Seymour給了你正確的答案,但要加上......
正如編譯器所說,C ++允許您在類體中聲明和定義靜態const整數類型 。 所以你可以這樣做:
class Foo
{
static const int someInt = 1;
static const short someShort = 2;
// etc.
};
並且您不能對任何其他類型執行此操作,在這種情況下,您應該在.cpp文件中定義它們。
從C ++ 11開始,它可以在constexpr
的類中完成。
class stat {
public:
// init inside class
static constexpr double inlineStaticVar = 22;
};
現在可以使用以下方法訪問變量:
stat::inlineStaticVar
靜態成員變量必須在類中聲明,然后在其外部定義!
沒有解決方法,只需將其實際定義放在源文件中即可。
從你的描述來看,它聞起來就像你沒有以正確的方式使用靜態變量。 如果他們永遠不會改變你應該使用常量變量,但你的描述太通用了,不能多說些什么。
靜態成員變量對於類的任何實例始終保持相同的值:如果更改一個對象的靜態變量,它也將對所有其他對象進行更改(事實上,您也可以在沒有該類實例的情況下訪問它們 - 即:一個對象)。
我覺得值得補充一點,靜態變量與常量變量不同。
在類中使用常量變量
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的值;
只是為了補充其他答案。 要初始化復雜的靜態成員 ,可以按如下方式執行:
像往常一樣聲明你的靜態成員。
// 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();
如果您的目標是初始化頭文件中的靜態變量(而不是* .cpp文件,如果您堅持使用“僅標題”慣用語,則可能需要該文件),那么您可以通過使用a來解決初始化問題模板。 模板化的靜態變量可以在標頭中初始化,而不會導致定義多個符號。
請看這里的例子:
(可選)將所有常量移動到.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;
}
一些答案似乎有點誤導 。
.cpp
文件以進行初始化,因為它可以在同一個Header文件中完成。 此外,您甚至可以使用inline
關鍵字初始化同一類范圍中的靜態對象,就像使用普通變量一樣。
在同一文件中初始化時沒有值
#include <string>
class A
{
static std::string str;
static int x;
};
std::string A::str;
int A::x;
使用同一文件中的值進行初始化
#include <string>
class A
{
static std::string str;
static int x;
};
std::string A::str = "SO!";
int A::x = 900;
使用inline
關鍵字在相同的類范圍中初始化
#include <string>
class A
{
static inline std::string str = "SO!";
static inline int x = 900;
};
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.