繁体   English   中英

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

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM