在 C++ 类中初始化静态变量?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5019856/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 17:12:11  来源:igfitidea点击:

Initialize static variables in C++ class?

c++staticinitialization

提问by Felix Dombek

I have noticed that some of my functions in a class are actually not accessing the object, so I made them static. Then the compiler told me that all variables they access must also be static – well, quite understandable so far. I have a bunch of string variables such as

我注意到我在一个类中的一些函数实际上没有访问该对象,所以我把它们static. 然后编译器告诉我他们访问的所有变量也必须是静态的——嗯,到目前为止还可以理解。我有一堆字符串变量,例如

string RE_ANY = "([^\n]*)";
string RE_ANY_RELUCTANT = "([^\n]*?)";

and so on in the class. I have then made them all static constbecause they never change. However, my program only compiles if I move them out of the class: Otherwise, MSVC++2010 complains "Only static constant integral variables may be initialized within a class".

等等在课堂上。然后我把它们都做了,static const因为它们永远不会改变。但是,我的程序只有在我将它们移出类时才会编译:否则,MSVC++2010 会抱怨“只有静态常量整数变量可以在类中初始化”。

Well that's unfortunate. Is there a workaround? I would like to leave them inside the class they belong to.

那很不幸。有解决方法吗?我想把他们留在他们所属的班级里。

回答by Mike Seymour

They can't be initialised inside the class, but they can be initialised outside the class, in a source file:

它们不能在类内部初始化,但可以在类外部的源文件中初始化:

// 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]*?)";

Update

更新

I've just noticed the first line of your question - you don'twant to make those functions static, you want to make them const. Making them staticmeans that they are no longer associated with an object (so they can't access any non-static members), and making the data static means it will be shared with all objects of this type. This may well not be what you want. Making them constsimply means that they can't modify any members, but can still access them.

我只注意到你的问题的第一线-你希望使这些功能static,你想他们const。使它们static意味着它们不再与对象相关联(因此它们不能访问任何非静态成员),并使数据静态意味着它将与此类型的所有对象共享。这很可能不是您想要的。制作它们const只是意味着它们不能修改任何成员,但仍然可以访问它们。

回答by Santiago V.

Mike Seymour has given you the right answer, but to add...
C++ lets you declare and define in your class body only static const integral types, as the compiler tells. So you can actually do:

Mike Seymour 已经给了你正确的答案,但要补充的是...
C++ 允许你在你的类体中声明和定义只有static const 整数类型,正如编译器所说。所以你实际上可以这样做:

class Foo
{
    static const int someInt = 1;
    static const short someShort = 2;
    // etc.
};

And you can't do that with any other type, in that cases you should define them in your .cpp file.

你不能用任何其他类型来做到这一点,在这种情况下,你应该在你的 .cpp 文件中定义它们。

回答by 0ax1

Since C++11 it can be done inside a class with constexpr.

从 C++11 开始,它可以在带有constexpr.

class stat {
    public:
        // init inside class
        static constexpr double inlineStaticVar = 22;
};

The variable can now be accessed with:

现在可以通过以下方式访问该变量:

stat::inlineStaticVar

回答by peoro

Static member variables must be declared in the class and then defined outside of it!

静态成员变量必须在类中声明,然后在类外定义!

There's no workaround, just put their actual definition in a source file.

没有解决方法,只需将它们的实际定义放在源文件中。



From your description it smells like you're not using static variables the right way. If they never change you should use constant variable instead, but your description is too generic to say something more.

根据您的描述,您似乎没有以正确的方式使用静态变量。如果它们永远不会改变,您应该改用常量变量,但您的描述过于笼统,无法多说。

Static member variables always hold the same value for any instance of your class: if you change a static variable of one object, it will change also for all the other objects (and in fact you can also access them without an instance of the class - ie: an object).

静态成员变量对于类的任何实例始终保持相同的值:如果您更改一个对象的静态变量,它也会更改所有其他对象(实际上您也可以在没有类实例的情况下访问它们 -即:一个对象)。

回答by thecoshman

I feel it is worth adding that a static variable is not the same as a constant variable.

我觉得值得补充的是,静态变量与常量变量不同。

using a constant variable in a class

在类中使用常量变量

struct Foo{
    const int a;
    Foo(int b) : a(b){}
}

and we would declare it like like so

我们会像这样声明它

fooA = new Foo(5);
fooB = new Foo(10);
// fooA.a = 5;
// fooB.a = 10;

For a static variable

对于静态变量

struct Bar{
    static int a;
    Foo(int b){
        a = b;
    }
}
Bar::a = 0; // set value for a

which is used like so

像这样使用

barA = new Bar(5);
barB = new Bar(10);
// barA.a = 10;
// barB.a = 10;
// Bar::a = 10;

You see what happens here. The constant variable, which is instanced along with each instance of Foo, as Foo is instanced has a separate value for each instance of Foo, and it can't be changed by Foo at all.

你看这里发生了什么。与每个 Foo 实例一起实例化的常量变量,因为 Foo 被实例化,对于每个 Foo 实例都有一个单独的值,并且它根本不能被 Foo 更改。

Where as with Bar, their is only one value for Bar::a no matter how many instances of Bar are made. They all share this value, you can also access it with their being any instances of Bar. The static variable also abides rules for public/private, so you could make it that only instances of Bar can read the value of Bar::a;

与 Bar 一样,无论创建了多少个 Bar 实例,它们都只是 Bar::a 的一个值。它们都共享此值,您也可以使用它们作为 Bar 的任何实例来访问它。静态变量也遵守公共/私有规则,因此您可以设置只有 Bar 的实例才能读取 Bar::a 的值;

回答by Sergio Basurco

Just to add on top of the other answers. In order to initialize a complex static member, you can do it as follows:

只是为了添加其他答案。为了初始化一个复杂的静态成员,你可以这样做:

Declare your static member as usual.

像往常一样声明你的静态成员。

// myClass.h
class myClass
{
static complexClass s_complex;
//...
};

Make a small function to initialize your class if it's not trivial to do so. This will be called just the one time the static member is initialized. (Note that the copy constructor of complexClass will be used, so it should be well defined).

如果这样做不是微不足道的,请创建一个小函数来初始化您的类。这将仅在静态成员初始化时调用一次。(注意会用到complexClass的拷贝构造函数,所以应该定义好)。

//class.cpp    
#include myClass.h
complexClass initFunction()
{
    complexClass c;
    c.add(...);
    c.compute(...);
    c.sort(...);
    // Etc.
    return c;
}

complexClass myClass::s_complex = initFunction();

回答by Beyondo

Some answers seem to be a little misleading.

有些答案似乎有点误导

You don't have to ...

你不必...

  • Assign a valueto some static object when initializing, because assigning a value is Optional.
  • Create another .cppfilefor initializing since it can be done in the same Headerfile.
  • 分配一个值初始化的时候,因为赋值是一些静态的对象可选
  • 创建另一个.cpp文件进行初始化,因为它可以在同一个头文件中完成。

Also, you can even initialize a static object in the same class scope just like a normal variable using the inlinekeyword.

此外,您甚至可以使用inline关键字在同一类范围内初始化静态对象,就像普通变量一样。



Initialize with no values in the same file

在同一个文件中不使用任何值进行初始化

#include <string>
class A
{
    static std::string str;
    static int x;
};
std::string A::str;
int A::x;

Initialize with values in the same file

使用同一文件中的值进行初始化

#include <string>
class A
{
    static std::string str;
    static int x;
};
std::string A::str = "SO!";
int A::x = 900;

Initialize in the same class scope using the inlinekeyword

使用inline关键字在同一个类范围内初始化

#include <string>
class A
{
    static inline std::string str = "SO!";
    static inline int x = 900;
};

回答by Mark Lakata

If your goal is to initialize the static variable in your header file (instead of a *.cpp file, which you may want if you are sticking to a "header only" idiom), then you can work around the initialization problem by using a template. Templated static variables can be initialized in a header, without causing multiple symbols to be defined.

如果您的目标是初始化头文件中的静态变量(而不是 *.cpp 文件,如果您坚持使用“仅限头文件”的习惯用法,您可能需要这种文件),那么您可以通过使用模板。模板化静态变量可以在标头中初始化,而不会导致定义多个符号。

See here for an example:

请参见此处的示例:

Static member initialization in a class template

类模板中的静态成员初始化

回答by RuslanK

Optionally, move all your constants to .cpp file without declaration in .h file. Use anonymous namespace to make them invisible beyond the cpp module.

或者,将所有常量移动到 .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;
}