3

現在、c ++でいくつかのWinRTカスタムコントロールを作成していますが、コンパイラー/インテリセンスから、静的コンストラクターは許可されていないと言われています。

静的データを設定する必要があります。プライベートboolインスタンスフラグを使用でき、クラスの最初のインスタンス化で静的データなどを作成できます(事実上同じことを実現します)。

しかし、これは少し時間がかかるように思われるので、私は何かを逃したかもしれません。

WinRT /c++での静的構築に対する標準的な代替アプローチは何ですか

ありがとう

4

3 に答える 3

6

クラス内で静的メンバーを宣言しますが、外部で定義する必要があります。

// In header file
class Foo
{
    static int bar;
    static int bar2;

    static int init_bar3() { return 123; }
};

// In source file
int Foo::bar;

// Define and intiailize
int Foo::bar2 = 5;

// For more complicated initialization
int Foo::bar3 = Foo::init_bar3();
于 2012-09-12T09:25:24.193 に答える
2

C++は静的コンストラクターをサポートしていません。ほとんどの場合、Joachim Pileborgの回答に示されているように、静的初期化を使用する必要があります。C ++をC#スタイルで記述しようとするのではなく、静的初期化を実行する慣用的なC++の方法に適応することをお勧めします。

ただし、C ++でC#スタイルの静的コンストラクターが本当に必要な場合は、それらを偽造することができます。

class Foo {
public:
  Foo() {
    static_constructor();//call must appear in every constructor
  }

  Foo(Bar bar, Baz baz) {
    static_constructor();//call must appear in every constructor
  }

private:    
  static void static_constructor() {
    static bool run = false;
    if( !run ) {
      run = true;
      //your logic goes here
    }
  }
};
于 2012-09-12T10:24:18.287 に答える
1

Joachim Pileborgが彼の回答で示しているように、グローバル変数は動的初期化子を持つことができ、C++およびC++/CXで「静的コンストラクター」の形式として使用できます。ラムダ式を使用して、初期化をローカルに保つことができることに注意してください。

int Foo::bar = [](){ return 123; }();

ただし、2つの理由から、可能であれば、これを行わないことをお勧めします。まず、グローバル変数が動的に初期化される順序は、部分的にしか指定されていません。別のソースファイルで定義されている他のグローバル変数に依存する動的初期化子がある場合、問題が発生する可能性があります。

次に、さらに重要なことに、WindowsランタイムコンポーネントはDLLであり、グローバル変数の動的初期化はDLL初期化の一部として発生します。これは、DLLのエントリポイントが呼び出されたときに発生します。MSDNがドキュメントに記載しているようにDllMain、「DLLエントリポイントで実行できることには重大な制限があります。」インターネットで「DllMain」を検索すると、DLLの初期化中にエキサイティングなことを行うことで発生する可能性のある問題を説明する多くのリソースが見つかります。

特に、別のDLLがロードされる可能性のあることを行うことは禁止されています。これは、一般に、DLLで定義されていないWindowsランタイムタイプは、それらが定義されているDLLがまだロードされていない可能性があるため、直接または間接的に使用できないことを意味します。動的初期化中に行われたエキゾチックな作業によって引き起こされたデッドロックに起因するいくつかのハングをデバッグしました。

したがって、別の方法として、グローバル変数を関数にカプセル化します...

class Foo {
public:
    static int bar() {
        static int value = [](){ return 123; }();
        return value;
    }
};

...そしてFoo::bar()の代わりに使用しFoo::barます。ブロックスコープの静的変数は、関数が最初に入力されたときに1回初期化されます。Foo::bar複数のスレッドから使​​用する場合は、初期化を同期する必要がある場合があることに注意してください。C ++ 11では、初期化がスレッドセーフである必要がありますが、Visual C ++はまだ(Visual C ++ 2012の時点で)C++11のこの機能をサポートしていません。

于 2012-09-14T18:04:27.590 に答える