首页 文章

在类定义中定义静态const整数成员

提问于
浏览
91

我的理解是C允许在类中定义静态const成员,只要它是整数类型即可 .

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

#include <algorithm>
#include <iostream>

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

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

我得到的错误是:

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

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

知道发生了什么事吗?

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

7 回答

  • 3

    我的理解是C允许在类中定义静态const成员,只要它是整数类型即可 .

    你是对的 . 您可以在类声明中初始化静态const积分,但这不是定义 .

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

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

    知道发生了什么事吗?

    std :: min通过const引用获取其参数 . 如果它按值获取它们你没有这个问题,但是因为你需要一个引用,你还需要一个定义 .

    这是章节/经文:

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

    请参阅Chu的答案,了解可能的解决方法 .

  • 42

    Bjarne Stroustrup的例子in his 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
        // ...
    }
    

    他说:“如果(并且只有)它具有异类定义,你可以获取静态成员的地址” . 这表明它会起作用 . 也许你的min函数会在幕后以某种方式调用地址 .

  • 3

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

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

    不只是int's . 但是您无法在类声明中定义该值 . 如果你有:

    class classname
    {
        public:
           static int const N;
    }
    

    在.h文件中你必须有:

    int const classname::N = 10;
    

    在.cpp文件中 .

  • 23

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

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

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

  • 10

    C允许在类中定义静态const成员

    不,3.1§2说:

    声明是一个定义,除非它声明一个函数而没有指定函数的主体(8.4),它包含extern说明符(7.1.1)或者链接规范(7.5),既不是初始化器也不是函数体,它声明了一个静态类定义中的数据成员(9.4),它是一个类名声明(9.1),它是一个opaque-enum-declaration(7.2),或者是一个typedef声明(7.1.3),一个using声明(7.3) .3),或使用指令(7.3.4) .

  • 9

    从C 11开始,你可以(并且你想)使用:

    static constexpr int N = 10;

    这不需要您在.cpp文件中定义常量 .

相关问题