次の作業コードがあります。
#include <string>
#include <iostream>
class A {
public:
const std::string test = "42";
//static const std::string test = "42"; // fails
};
int main(void){
A a;
std::cout << a.test << '\n';
}
テストをaにすることができない正当な理由はありstatic const
ますか? C++ 11より前は、標準によって制約されていたことを理解しています。私は、c++11 がクラス内初期化を導入して、少し使いやすくしたと考えました。私もかなり前から、そのようなセマンティックは整数型に使用できません。
もちろん、次の形式のクラス外初期化で機能しますconst std::string A::test = "42";
非静的にすることができれば、問題は2つのうちの1つにあると思います。クラス外スコープで初期化します (通常const
、オブジェクトのインスタンス化中に s が作成されます)。しかし、クラスの他のメンバーから独立したオブジェクトを作成している場合、これは問題ではないと思います。2 つ目は、静的メンバーに複数の定義があることです。たとえば、複数に含まれている場合.cpp
ファイルがいくつかのオブジェクト ファイルに到達すると、リンカはそれらのオブジェクトを一緒にリンクするときに (たとえば、1 つの実行可能ファイルに)、同じシンボルのコピーが含まれるため、問題が発生します。私の理解では、これはヘッダーのクラス宣言のすぐ下にクラス外を提供し、この共通ヘッダーを複数の場所に含める状況とまったく同じです。私が思い出したように、これはリンカーエラーにつながります。
ただし、これを処理する責任はユーザー/プログラマーに移されました。ライブラリにstatic
クラス外の定義を提供する必要がある場合は、それを別のオブジェクト ファイルにコンパイルしてから、他のすべてのオブジェクトをこのファイルにリンクする必要があります。シンボル。
クラス定義内で初期化されている場合でも、静的メンバーを個別に定義する必要がありますか?の回答を読みました。クラスで非 const 静的メンバーまたは静的配列を初期化できないのはなぜですか? .
私はまだ知りたいです:
- それは単なる標準的なものですか、それとももっと深い理由がありますか?
constexpr
これは、およびユーザー定義のリテラル メカニズムで回避できますか。clang と g++ はどちらも、変数に非リテラル型を含めることはできないと言っています。多分私はそれを作ることができます。(たぶん、何らかの理由でそれも悪い考えです)- リンカーがシンボルのコピーを 1 つだけ含めることは、本当に大きな問題なのでしょうか? それは
static const
すべて、バイナリの正確な不変のコピーである必要があるためです。
私が何かを見逃したり誤解したりする場合は、コメントしてください。