C++ 在类定义中定义静态常量整数成员

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3025997/
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 11:50:57  来源:igfitidea点击:

Defining static const integer members in class definition

c++staticdeclarationdefinition

提问by HighCommander4

My understanding is that C++ allows static const members to be defined inside a class so long as it's an integer type.

我的理解是 C++ 允许在类中定义静态常量成员,只要它是整数类型。

Why, then, does the following code give me a linker error?

那么,为什么下面的代码会给我一个链接器错误?

#include <algorithm>
#include <iostream>

class test
{
public:
    static const int N = 10;
};

int main()
{
    std::cout << test::N << "\n";
    std::min(9, test::N);
}

The error I get is:

我得到的错误是:

test.cpp:(.text+0x130): undefined reference to `test::N'
collect2: ld returned 1 exit status

Interestingly, if I comment out the call to std::min, the code compiles and links just fine (even though test::N is also referenced on the previous line).

有趣的是,如果我注释掉对 std::min 的调用,代码编译和链接就好了(即使 test::N 在前一行也被引用)。

Any idea as to what's going on?

知道发生了什么吗?

My compiler is gcc 4.4 on Linux.

我的编译器是 Linux 上的 gcc 4.4。

采纳答案by Edward Strange

My understanding is that C++ allows static const members to be defined inside a class so long as it's an integer type.

我的理解是 C++ 允许在类中定义静态常量成员,只要它是整数类型。

You are sort of correct. You are allowed to initialize static const integrals in the class declaration but that is not a definition.

你说得对。您可以在类声明中初始化静态常量积分,但这不是定义。

http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=/com.ibm.xlcpp8a.doc/language/ref/cplr038.htm

http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=/com.ibm.xlcpp8a.doc/language/ref/cplr038.htm

Interestingly, if I comment out the call to std::min, the code compiles and links just fine (even though test::N is also referenced on the previous line).

有趣的是,如果我注释掉对 std::min 的调用,代码编译和链接就好了(即使 test::N 在前一行也被引用)。

Any idea as to what's going on?

知道发生了什么吗?

std::min takes its parameters by const reference. If it took them by value you'd not have this problem but since you need a reference you also need a definition.

std::min 通过常量引用获取其参数。如果按价值计算它们,您就不会遇到这个问题,但由于您需要参考,因此您还需要一个定义。

Here's chapter/verse:

这是章节/诗句:

9.4.2/4- If a staticdata member is of constintegral or constenumeration type, its declaration in the class definition can specify a constant-initializerwhich shall be an integral constant expression (5.19). In that case, the member can appear in integral constant expressions. The member shall still be defined in a namespace scope if it is used in the program and the namespace scope definition shall not contain an initializer.

9.4.2/4- 如果一个static数据成员是const整型或const枚举类型,它在类定义中的声明可以指定一个常量初始化器,它应该是一个整型常量表达式(5.19)。在这种情况下,成员可以出现在整数常量表达式中。如果在程序中使用该成员,则该成员仍应在名称空间范围内定义,并且名称空间范围定义不应包含初始化程序

See Chu's answer for a possible workaround.

有关可能的解决方法,请参阅 Chu 的回答。

回答by HostileFork says dont trust SE

Bjarne Stroustrup's example in his C++ FAQsuggests you are correct, and only need a definition if you take the address.

Bjarne Stroustrup在他的 C++ FAQ 中的例子表明你是正确的,如果你接受地址,只需要一个定义。

class AE {
    // ...
public:
    static const int c6 = 7;
    static const int c7 = 31;
};

const int AE::c7;   // definition

int f()
{
    const int* p1 = &AE::c6;    // error: c6 not an lvalue
    const int* p2 = &AE::c7;    // ok
    // ...
}

He says "You can take the address of a static member if (and only if) it has an out-of-class definition". Which suggests it would work otherwise. Maybe your min function invokes addresses somehow behind the scenes.

他说:“当(且仅当)静态成员具有类外定义时,您才能获取它的地址”。这表明它会以其他方式工作。也许您的 min 函数在幕后以某种方式调用了地址。

回答by Stephen Chu

Another way to do this, for integer types anyway, is to define constants as enums in the class:

无论如何,对于整数类型,另一种方法是将常量定义为类中的枚举:

class test
{
public:
    enum { N = 10 };
};

回答by Amardeep AC9MF

Not just int's. But you can't define the value in the class declaration. If you have:

不仅仅是int。但是您不能在类声明中定义该值。如果你有:

class classname
{
    public:
       static int const N;
}

in the .h file then you must have:

在 .h 文件中,您必须具有:

int const classname::N = 10;

in the .cpp file.

在 .cpp 文件中。

回答by karadoc

Here's another way to work around the problem:

这是解决该问题的另一种方法:

std::min(9, int(test::N));

(I think Crazy Eddie's answer correctly describes why the problem exists.)

(我认为 Crazy Eddie 的回答正确地描述了问题存在的原因。)

回答by Carlo Wood

As of C++11 you can use:

从 C++11 开始,您可以使用:

static constexpr int N = 10;

static constexpr int N = 10;

This theoretically still requires you to define the constant in a .cpp file, but as long as you don't take the address of Nit is very unlikely that any compiler implementation will produce an error ;).

这理论上仍然需要您在 .cpp 文件中定义常量,但只要您不获取N它的地址,任何编译器实现都不太可能产生错误;)。

回答by fredoverflow

C++ allows static const members to be defined inside a class

C++ 允许在类中定义静态常量成员

Nope, 3.1 §2 says:

不,3.1 §2 说:

A declaration is a definition unlessit declares a function without specifying the function's body (8.4), it contains the extern specifier (7.1.1) or a linkage-specification (7.5) and neither an initializer nor a functionbody, it declares a static data member in a class definition(9.4), it is a class name declaration (9.1), it is an opaque-enum-declaration (7.2), or it is a typedef declaration (7.1.3), a using-declaration (7.3.3), or a using-directive (7.3.4).

声明是一个定义,除非它声明一个函数而没有指定函数体 (8.4),它包含 extern 说明符 (7.1.1) 或链接规范 (7.5) 并且既没有初始化程序也没有函数体,它声明了一个静态数据类定义(9.4) 中的成员,它是一个类名声明 (9.1),它是一个不透明枚举声明 (7.2),或者它是一个 typedef 声明 (7.1.3),一个 using 声明 (7.3. 3) 或 using 指令 ​​(7.3.4)。