ソースファイルで静的データメンバーを定義する理由を読みました。それらがヘッダーファイルにあり、複数のソースファイルにヘッダーファイルが含まれている場合、定義が複数回出力されるためです。これが静的constデータメンバーにとって問題になる理由はわかりますが、なぜこれが静的データメンバーにとって問題になるのでしょうか。
定義がヘッダーファイルに記述されている場合に問題が発生する理由を完全に理解しているのかよくわかりません...
変数の複数定義の問題は、言語定義の2つの主な欠陥が原因です。
以下に示すように、簡単に回避できます。直接サポートがない技術的な理由はありません。それは、委員会の人々がそれを優先することを選択したという十分に高い需要がないという機能と関係があります。
まず、一般的に複数の定義が問題になる理由。C ++は個別にコンパイルされたモジュール(欠陥#1)をサポートしていないため、プログラマーはテキストによる前処理などを使用してその機能をエミュレートする必要があります。そうすると、同じ名前の2つ以上の定義を誤って導入する可能性が高くなります。
関数の場合、これはinline
キーワードとプロパティによって解決されました。自立関数は明示的にのみ指定inline
できますが、メンバー関数inline
はクラス定義で定義することにより暗黙的に指定できます。いずれにせよ、関数がそうである場合、inline
それは複数の変換単位で定義でき、それが使用されるすべての変換単位で定義されなければならず、それらの定義は同等でなければなりません。
主にそのソリューションでは、クラスをヘッダーファイルで定義できました。
データ、ヘッダーファイルで定義された変数をサポートするためにそのような言語機能は必要なかったので、それはただそこにありませんinline
。変数を持つことはできません。これが言語不足#2です。
ただし、クラステンプレートのデータメンバーに対する特別な免除を介して、変数の効果を取得できます。免除の理由は、クラステンプレートは通常ヘッダーファイルで完全に定義する必要があるため(テンプレートが翻訳ユニットの内部でのみ使用される場合を除く)、クラステンプレートがデータメンバーを持つことができるようにするには、次のいずれかで必要です。一般規則の免除、または特別なサポート。委員会は、規則からの免税ルートを選択しました。inline
static
static
template< class Dummy >
struct math_
{
static double const pi;
};
template< class Dummy >
double const math_<Dummy>::pi = 3.14;
typedef math_<void> math;
上記は、テンプレート化されたconstトリックと呼ばれています。私の知る限り、[comp.lang.c ++] Usenetグループでかつてそれを紹介したのは私だったので、他の誰かの功績を認めることはできません。また、ここSOに数回投稿しました。
とにかく、これは、すべてのC ++コンパイラとリンカがデータに必要な機構を内部的にサポートし、サポートする必要があることを意味しますinline
が、言語にはその機能がありません。
ただし、第3に、C ++ 11にはconstexpr
、上記を次のように記述できます。
struct math
{
static double constexpr pi = 3.14;
};
違いは、C ++ 11のアドレスを取得できないことですが、math::pi
これは非常に小さな制限です。
あなたは2つのことを混同していると思います:static
データメンバーとグローバル変数はとしてマークしstatic
ます。
後者には内部リンケージがあります。つまり、複数の変換ユニットの定義をヘッダーファイルに入れると、各変換ユニットはそれらの変数のプライベートコピー#include
を受け取ります。
としてマークされたグローバル変数はconst
デフォルトで内部リンケージがあるため、それらを明示的に指定する必要はありませんstatic
。したがって、リンカは、グローバル変数またはとしてマークされたconst
グローバル非変数の複数の定義について文句を言うことはありませんが、他の場合は文句を言います(これらの変数には外部リンケージがあるため)。const
static
データメンバーに関してstatic
は、これはC++11標準のパラグラフ9.4.2/5が述べていることです。
static
名前空間スコープのクラスのデータメンバーには、外部リンケージ(3.5)があります。ローカルクラスにはstatic
データメンバーを含めないものとします。
つまり、#include
複数の変換ユニットによってヘッダーファイルdにそれらの定義を配置すると、それらの修飾がconst
何であっても、対応するオブジェクトファイル(非グローバル変数とまったく同じ)に同じシンボルの複数の定義が作成されます。 const
。その場合、プログラムは単一定義規則に違反します。
また、StackOverflowに関するこのQ&Aにより、主題をより明確に理解できる場合があります。