私の理解では、整数型である限り、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です。
私の理解では、整数型である限り、C++では静的constメンバーをクラス内で定義できます。
あなたは一種の正しいです。クラス宣言で静的const積分を初期化することはできますが、これは定義ではありません。
興味深いことに、std :: minの呼び出しをコメントアウトすると、コードはコンパイルされ、リンクが正常に行われます(test :: Nも前の行で参照されていますが)。
何が起こっているのか考えていますか?
std :: minは、const参照によってパラメーターを受け取ります。値で取得した場合、この問題は発生しませんが、参照が必要なため、定義も必要です。
ここに章/詩があります:
9.4.2/4 -static
データメンバがconst
整数型またはconst
列挙型の場合、クラス定義でのその宣言は、 定数初期化子 整数定数式(5.19)でなければなりません。その場合、メンバーは整数定数式で表示できます。メンバーは、プログラムで使用されている場合、名前空間スコープで定義され、名前空間スコープ定義には 初期化子。
可能な回避策については、Chuの回答を参照してください。
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
// ...
}
彼は言います 「静的メンバーのアドレスを取得できるのは、クラス外の定義がある場合(およびその場合のみ)」。それはそれがそうでなければ動作することを示唆しています。たぶん、あなたのmin関数は舞台裏でアドレスを呼び出します。
これを行う別の方法は、とにかく整数型の場合、定数をクラスの列挙として定義することです。
class test
{
public:
enum { N = 10 };
};
Intだけではありません。ただし、クラス宣言で値を定義することはできません。あなたが持っている場合:
class classname
{
public:
static int const N;
}
.hファイルには、次のものが必要です。
int const classname::N = 10;
.cppファイル内。
問題を回避する別の方法を次に示します。
std::min(9, int(test::N));
(Crazy Eddieの答えは、問題が存在する理由を正しく説明していると思います。)
C++ 11以降では、次を使用できます。
static constexpr int N = 10;
理論的には、.cppファイルで定数を定義する必要がありますが、N
のアドレスを取得しない限り、コンパイラの実装でエラーが発生することはほとんどありません;)。
C++では、クラス内で静的constメンバーを定義できます。
いいえ、3.1§2のコメント:
宣言は定義でない限り関数の本体を指定せずに関数を宣言し(8.4)、extern指定子(7.1.1)またはリンケージ仕様(7.5)を含み、初期化子もfunctionbody、クラス定義で静的データメンバーを宣言(9.4)、クラス名宣言(9.1)、opaque-enum-declaration(7.2)、またはtypedef宣言(7.1.3)、使用宣言(7.3.3)、または使用ディレクティブ(7.3.4)。