简体   繁体   English

static const in c++ class:未定义引用

[英]static const in c++ class: undefined reference

I have a class for local use only (ie, its cope is only the c++ file it is defined in)我有一个 class 仅供本地使用(即,它的副本只是它定义的 c++ 文件)

class A {
public:
    static const int MY_CONST = 5;
};

void fun( int b ) {
    int j = A::MY_CONST;  // no problem
    int k = std::min<int>( A::MY_CONST, b ); // link error: 
                                            // undefined reference to `A::MY_CONST` 
}

All the code reside in the same c++ file.所有代码都位于同一个 c++文件中。 When compiling using VS on windows, there is no problem at all.在windows上用VS编译时,完全没有问题。
However, when compiling on Linux I get the undefined reference error only for the second statement.但是,在 Linux 上编译时,我只得到第二条语句的undefined reference错误。

Any suggestions?有什么建议么?

std::min<int> 's arguments are both const int& (not just int ), ie references to int . std::min<int>的参数都是const int& (不仅仅是int ),即对int 引用 And you can't pass a reference to A::MY_CONST because it is not defined (only declared ). 并且您不能传递对A::MY_CONST的引用,因为它未定义 (仅声明 )。

Provide a definition in the .cpp file, outside the class: 在类外部的.cpp文件中提供定义:

class A {
public:
    static const int MY_CONST = 5; // declaration
};

const int A::MY_CONST; // definition (no value needed)
// initialize static constants outside the class

class A {
public:
    static const int MY_CONST;
};

const int A::MY_CONST = 5;

void fun( int b ) {
    int j = A::MY_CONST;  // no problem
    int k = std::min<int>( A::MY_CONST, b ); // link error: 
                                            // undefined reference to `A::MY_CONST` 
}

To explain what's happening here: 要解释这里发生的事情:

You declared static const integer inside class, this "feature" is here to be able to use it as constant expression ,ie for local array size, template non-type parameters, etc.. If compiler wants to use this constant expression it must be able to see it's value in that translation unit. 你在类中声明了static const整数,这个“特性”在这里可以将它用作常量表达式 ,即用于本地数组大小,模板非类型参数等。如果编译器想要使用这个常量表达式,它必须是能够在翻译单元中看到它的价值。

9.5/3 9.5 / 3

If a non-volatile const static data member is of integral or enumeration type, its declaration in the class definition can specify a brace-or-equal-initializer in which every initializer-clause that is an assignment expression is a constant expression (5.19). 如果非易失性const静态数据成员是整数类型或枚举类型,则它在类定义中的声明可以指定一个大括号或等于初始化器,其中作为赋值表达式的每个initializer子句都是一个常量表达式(5.19) 。 A static data member of literal type can be declared in the class definition with the constexpr specifier; 可以使用constexpr指定器在类定义中声明文字类型的静态数据成员; if so, its declaration shall specify a brace-or-equal-initializer in which every initializer-clause that is an assignment-expression is a constant expression. 如果是这样,它的声明应指定一个大括号或等于初始化器,其中作为赋值表达式的每个initializer子句都是一个常量表达式。 [ Note: In both these cases, the member may appear in constant expressions . [注意: 在这两种情况下,成员可能会出现在常量表达式中 — end note ] The member shall still be defined in a namespace scope if it is odr-used (3.2) in the program and the namespace scope definition shall not contain an initializer . - 结束注释] 如果程序中使用了odr-used (3.2),并且命名空间作用域定义不包含初始化程序,则该成员仍应在命名空间作用域中定义。

odr-used means to form reference to that variable or take it's address. odr-used意味着形成对该变量的引用或获取它的地址。

std::min takes it's parameters by reference, so they are odr-used . std::min通过引用获取它的参数,因此它们使用的是odr

Solution: 解:

Define it! 定义它!

class A
{
    static const int a = 5;
};

const int A::a; //definition, shall not contain initializer

I am having a very strange situation 我的情况非常奇怪

template<class T> class Strange {

public:
  static const char gapchar='-';
  };

template<class T> void Strange<T> method1 {
      char tmp = gapchar;
}

template<class T> void Strange<T> method2 {
    char tmp = gapchar;
}

I include the above class, it has been working for several years. 我包括上面的课程,它已经工作了几年。

I added another method, essentially the same signature and just reading the gapchar. 我添加了另一种方法,基本上是相同的签名,只是读取gapchar。

I got undefined error only for the third method, even I am using all three methods. 我只为第三种方法得到了未定义的错误,即使我使用了所有三种方法。

Then I changed the way I initialize the static variable by 然后我改变了初始化静态变量的方式

not initializing in the class definition: 不在类定义中初始化:

static const char gapchar;

template<class T> const char Strange<T>::gapchar='-';

This solved the problem. 这解决了这个问题。 I could not figure out why the old way of initializing int or char type (the only two types allowed) inside the class definition section stop working for only one of the methods but not others. 我无法弄清楚为什么在类定义部分中初始化int或char类型(只允许两种类型)的旧方法只停止其中一种方法而不是其他方法。

You can also save the const value to a local variable. 您还可以将const值保存到局部变量。

class A {
public:
    static const int MY_CONST = 5;
};

void fun( int b ) {
    int j = A::MY_CONST;  // no problem
    int k = std::min<int>( A::MY_CONST, b ); // link error: undefined reference to `A::MY_CONST` 
    int l = std::min<int>( j, b);  // works
}

If you are using some header-only thing and want to avoid having to add a .cpp file, it seems like you can do this:如果您正在使用一些仅标头的东西并且想避免必须添加.cpp文件,那么您似乎可以这样做:

class A {
public:
    static inline const int MY_CONST = 5;
};

(or `static inline constexpr`)

This requires C++17

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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