C++ のさまざまな定数宣言および定義オプションの利点と欠点について興味があります。長い間、クラス定義の前のヘッダー ファイルの先頭でそれらを宣言してきました。
//.h
const int MyConst = 10;
const string MyStrConst = "String";
class MyClass {
...
};
これはグローバル名前空間を汚染しますが (これは悪いことだとわかっていますが、なぜ悪いことなのかという理由を列挙したリストは見たことがありません)、定数は個々の翻訳単位にスコープが限定されるため、このヘッダーを含まないファイルはこれらの定数にアクセスできません。ただし、他のクラスが同じ名前の定数を定義すると、名前の衝突が発生する可能性があります。これは、リファクタリングできる領域を示す良い指標になる可能性があるため、悪いことではないと言えます。
最近、クラス定義自体の中でクラス固有の定数を宣言する方が良いと判断しました。
//.h
class MyClass {
public:
static const int MyConst = 10;
...
private:
static const string MyStrConst;
...
};
//.cpp
const string MyClass::MyStrConst = "String";
定数の可視性は、定数がクラス内部でのみ使用されるか、クラスを使用する他のオブジェクトに必要かによって調整されます。これが現時点では最善の選択肢だと私は考えています。主な理由は、内部クラス定数をクラス専用にしておくことができ、パブリック定数を使用する他のクラスは定数のソースへのより詳細な参照を持つことができるためです (例: MyClass::MyConst)。また、グローバル名前空間を汚染することもありません。ただし、cpp ファイルで非整数初期化が必要になるというデメリットがあります。
また、他のクラスで定数が必要であっても、クラス定義全体が必要ない場合に備えて、定数を独自のヘッダー ファイルに移動し、名前空間でラップすることも検討しました。
ただ意見や、まだ考慮していなかった他の選択肢を探しているだけです。
ベストアンサー1
非整数定数を静的クラスメンバーとして宣言すると「cppファイルで非整数初期化が必要になるというデメリットがある」というあなたの主張は、いわば、厳密には確固たるものではありません。cppファイルでの定義は必要ですが、それは「デメリット」ではなく、あなたの意図の問題です。C const
++の名前空間レベルのオブジェクトはデフォルトで内部リンクを持ちます。つまり、あなたの元のバリアントでは、宣言
const string MyStrConst = "String";
は以下と同等である
static const string MyStrConst = "String";
MyStrConst
つまり、このヘッダー ファイルがインクルードされるすべての翻訳単位で独立したオブジェクトが定義されます。このことに気づいていますか? これは意図したものでしょうか?
いずれにせよ、もしあなたが具体的には翻訳単位ごとに別々のオブジェクトが必要な場合は、MyStrConst
元の例の定数の宣言は良い方法ではありません。通常は、ヘッダーファイルに非定義宣言のみを配置します。
extern const string MyStrConst;
cppファイルに定義を提供する
const string MyStrConst = "String";
これにより、プログラム全体で同じ定数オブジェクトが使用されるようになります。言い換えると、非整数定数の場合、通常は cpp ファイルで定義します。したがって、どのように宣言するか (クラス内またはクラス外) に関係なく、通常は cpp ファイルで定義する必要があるという「デメリット」に常に対処する必要があります。もちろん、上で述べたように、名前空間定数では最初のバリアントにあるものを使用してもかまいませんが、これは「怠惰なコーディング」の例にすぎません。
いずれにせよ、問題を過度に複雑にする理由はないと思います。定数がクラスに明らかに「関連付けられている」場合は、クラス メンバーとして宣言する必要があります。
PS アクセス指定子 ( public
、protected
、private
) は制御しません可視性名前の所有権は、アクセシビリティいずれの場合も名前は表示されたままになります。