C ++で誤ってグローバル定数を再宣言しないようにするにはどうすればよいですか?
-
22-07-2019 - |
質問
" Matrix.h"というヘッダーで定義されたテンプレートマトリックスクラスクラスがあります。
特定の行列がプログラムで繰り返し使用されています。これらを「Matrix.h」で定義すると思いました。次のようなヘッダーファイル:
const Matrix<GLfloat> B_SPLINE_TO_BEZIER_MATRIX(4, 4, values);
これを行うと、g ++は問題の定数を再定義したと文句を言います。これは、2つの異なるソースファイルにMatrix.hを含めるために発生します。これらのオブジェクトファイルがコンパイルされると、両方とも上記のマトリックスの定義になり、エラーメッセージが表示されます。
私の質問は、この状況をどのように回避すればよいですか?複数のファイルからアクセス可能な定数が必要ですが、どこに配置するかわかりません。
解決
ヘッダーと実装ファイルに分割したくない場合は、
-
定数
static
を宣言(または匿名名前空間で宣言)して、定義をプライベートにします。リンカは文句を言いませんが、コンパイルユニット間で複数のプライベートコピーを作成します。static Matrix<GLfloat> B_SPLINE_TO_BEZIER_MATRIX(4, 4, values);
-
定数を返すインライン関数を作成します。インライン関数定義は、「弱い」を生成します。オブジェクトファイル内のシンボル。したがって、リンカは重複を排除し、1つを選択します。
inline const Matrix<GLfloat>& GET_B_SPLINE_TO_BEZIER_MATRIX() { const static Matrix<GLfloat> B_SPLINE_TO_BEZIER_MATRIX(4, 4, values); return B_SPLINE_TO_BEZIER_MATRIX; }
他のヒント
次の方法で回避します:
- ヘッダーで
extern
を宣言します。シンボルは何度でも宣言できます。 - 実装で一度だけ定義します。
このようにヘッダーファイルを記述するだけです
#ifndef HEADER_FILE_NAME_H
#define HEADER_FILE_NAME_H
//ヘッダーファイルコード
#endif
これにより、複数回宣言されないようになります
プリプロセッサ条件でヘッダーファイル(.h)をラップして、コンパイラのシンボルテーブルに2回含まれないようにします。
#ifndef HEADER_NAME
#define HEADER_NAME
// code...
#endif//HEADER_NAME
HEADER_NAMEは実際には何でも構いませんが、空のプリプロセッサマクロ(これもシンボルテーブルになります)を定義するだけなので、衝突を防ぐためにファイルに関連するものにすることをお勧めします。