30

C ++に静的コンストラクターがない理由は何ですか?

許可されている場合は、次のように、非常に整理された方法で、その中のすべての静的メンバーを1か所で初期化します。

//illegal C++
class sample
{
public:

    static int some_integer;
    static std::vector<std::string> strings;

    //illegal constructor!
    static sample()
    {
       some_integer = 100;
       strings.push_back("stack");
       strings.push_back("overflow");
    }
};

静的コンストラクターがない場合、上記のように静的ベクトルを作成し、それに値を設定することは非常に困難です。静的コンストラクターは、この問題をエレガントに解決します。非常に組織化された方法で静的メンバーを初期化できます。

では、なぜC++に静的コンストラクターがないのでしょうか。結局のところ、他の言語(たとえば、C#)には静的コンストラクターがあります!

4

5 に答える 5

22

この機能を言語に導入しない言い訳として静的初期化順序の問題を使用することは、常に現状の問題です-導入されなかったために導入されなかったため、初期化順序は理由ではないと人々は考え続けています注文の問題に単純で非常に簡単な解決策がある場合でも、それを紹介します。

初期化の順序。人々が本当に問題に取り組みたいと思っていたとしたら、彼らは非常に単純で簡単な解決策を持っていただろう。

//called before main()

int static_main() {

ClassFoo();
ClassBar();

}

適切な宣言付き:

class ClassFoo {
 static int y;
  ClassFoo() {
   y = 1;
  }
}

class ClassBar {
  static int x;
  ClassBar() {
   x = ClassFoo::y+1;
  }
}

つまり、答えは、それが存在しない理由はなく、少なくとも技術的な理由はないということです。

于 2011-03-14T16:59:53.420 に答える
14

これは、C ++では実際には意味がありません。クラスはファーストクラスのオブジェクトではありません(Javaなど)。

(static | anything)コンストラクターは、何かが構築されることを意味します。c++クラスは構築されませんが、構築されるだけです。

ただし、同じ効果を簡単に実現できます。

//.h
struct Foo {
  static std::vector<std::string> strings;
};
//.cpp
std::vector<std::string> Foo::strings(createStrings());

IMOは、これを行うためのもう1つの構文上の方法は必要ありません。

于 2011-03-14T16:54:37.850 に答える
6

静的オブジェクトはどの変換ユニットに配置されますか?

静力学を1つ(そして1つだけ)のTUに配置する必要があるという事実を考慮すれば、残りの方法を実行して、関数でそれらに値を割り当てることは「非常に難しい」ことではありません。

// .h
class sample
{
public:
    static int some_integer;
    static std::vector<std::string> strings;
};

//.cpp

// we'd need this anyway
int sample::some_integer;
std::vector<std::string> sample::strings;

// add this for complex setup
struct sample_init {
    sample_init() {
       sample::some_integer = 100;
       sample::strings.push_back("stack");
       sample::strings.push_back("overflow");
    }
} x;

sample_initのコードをクラスの定義に表示したい場合はsample、ネストされたクラスとしてそこに配置することもできます。スタティックを定義するのと同じ場所でインスタンスを定義する必要があります(デフォルトのコンストラクターを介して初期化された後push_back、それ以外の場合はもちろん何もできません)。

C#はC ++から15〜20年後に発明され、ビルドモデルがまったく異なります。さまざまな機能を提供していることや、C ++の方がC#よりも単純でないこともそれほど驚くことではありません。

C ++ 0xには、「初期化リスト」と呼ばれる、いくつかのデータを使用してベクトルを初期化するのを容易にする機能が追加されています。

于 2011-03-14T17:03:45.677 に答える
5

初期化を実行する独自のコンストラクターを使用して、「静的」メンバーを独自のクラスに配置することで解決できます。

class StaticData
{
    int some_integer;
    std::vector<std::string> strings;

public:
    StaticData()
    {
       some_integer = 100;
       strings.push_back("stack");
       strings.push_back("overflow");
    }
}

class sample
{    
    static StaticData data;

public:
    sample()
    {

    }
};

静的dataメンバーは、最初にアクセスを試みる前に初期化されることが保証されています。(おそらくメインの前ですが、必ずしもそうとは限りません)

于 2011-03-14T17:03:32.947 に答える
2

静的とは、オブジェクトとの関連付けが解除された関数を意味します。オブジェクトのみが構築されるため、静的コンストラクターにメリットがある理由は明らかではありません。

静的ブロックで構築された静的スコープにオブジェクトをいつでも保持できますが、使用するコンストラクターは非静的として宣言されます。静的スコープから非静的メソッドを呼び出せないことを示すルールはありません。

最後に、C ++ / Cは、main関数が入力されたときのプログラムの開始を定義します。静的ブロックはmain、評価されたコードの「環境」を設定する一環として、関数が入力される前に呼び出されます。ご使用の環境でセットアップとティアダウンを完全に制御する必要がある場合は、プログラムの手続き型コンポーネントを継承するほど、実際には環境フィクスチャではないと主張するのは簡単です。私は最後のビットが一種のコード哲学であることを知っています(そしてそれの論理的根拠は異なって解釈される可能性があります)が、実行可能ファイルが書かれたコードに「フルコントロール」を渡す公式の開始の「前」に重要なコードを置くべきではありませんプログラマーによる。

于 2011-03-14T16:51:32.597 に答える