0

C++ で書かなければならない C# コードがたくさんあります。私は C++ の経験があまりありません。

Visual Studio 2012 を使用してビルドしています。プロジェクトは C++ のスタティック ライブラリです (C++/CLI ではありません)。

私はいくつかの UnitTests を作成しています。C# バージョンでは、クラスTestData 、 TestDataの多数の静的インスタンス、およびそれらの静的インスタンスに値を設定する静的なInitializeメソッドがあります。

C++ で同じことをしようとすると、Initialize メソッドが TestData クラス内で宣言されている場合、機能しないことがわかりました。しかし、外部で宣言すると機能します。

C++ (テスト)

TEST_CLASS(UnitTest1)
{
public:
    TEST_CLASS_INITIALIZE(ClassInitialize)
    {
        TestData::Initialize();
    }

    TEST_METHOD(TestMethod1)
    {
        Assert::AreEqual(data0.testValue, 30);          
    }
};

C++ (TestData クラス内のメソッドを初期化) :

このように宣言された Initialize メソッドでは、テストは失敗します。デバッグすると、testValue が設定されているのがわかりますが、アセットに到達すると 0 に戻ります。

//.h
namespace Data
{
    class TestData
    {
    public:
        TestData(void);
        ~TestData(void);

    int testValue;

        static void Initialize();       
    };

    static TestData data0 = TestData();
}


    //.cpp
namespace Data
{
    TestData::TestData(void){}
    TestData::~TestData(void){}

    void TestData::Initialize()
    {
        data0.testValue = 30;
    }
}

C++ (クラス外で宣言されたメソッドを初期化):

このようなコードで、私のテストは機能します。

    //.h
namespace Data
{
    class TestData
    {
    public:
        TestData(void);
        ~TestData(void);
        int testValue;      
    };

static TestData data0 = TestData();

    static void Initialize()
    {
        data0.testValue = 30;
    }
}

なぜこうなった?

アップデート:

Hans のアドバイスに従って、使用されている変数のアドレスを追跡しました。何らかの理由でTestDataのコンストラクターが 2 回呼び出されていることに気付きました。どうしてか分かりません。自動割り当てが呼び出されているのではないかと思ったので、コンストラクターにintパラメーターを追加して、何が起こるかを確認しました.data0のコンストラクターを2回呼び出すようです。

テストが機能しない場合 (クラス内に Initialize がある場合)、呼び出し順序は次のとおりです。

  1. TestData (data0) コンストラクタ (アドレス: 1)
  2. TestData (data0) コンストラクタ (アドレス: 2)
  3. 初期化:アドレス 1で data0 を使用
  4. テスト:アドレス 2で data0 を使用

私のテストが機能する場合(クラス外でinitialzeを使用する場合)、呼び出し順序は次のとおりです。

  1. TestData (data0) コンストラクタ (アドレス: 1)
  2. TestData (data0) コンストラクタ (アドレス: 2)
  3. 初期化:アドレス 2で data0 を使用
  4. テスト:アドレス 2で data0 を使用

これで、テストが失敗する理由がわかりました。しかし、なぜコンストラクターが 2 回呼び出されるのか、なぜ 1 つのケースでは両方のインスタンスが使用され、別のケースでは 2 番目のインスタンスのみが使用されているのかわかりません。

4

1 に答える 1

1

実際には、Initialize 関数が Class 内で定義されているか、クラス外で定義されているかは問題ではないと思います。これは、グローバル変数 data0 と関数定義が同じファイルにないためです。

C++ の static コンストラクトには、グローバル変数に関する別の意味があります。つまり、変数は現在のファイルでのみ表示されます。

ヘッダー ファイルで「static TestData data0 = TestData()」を定義し、cpp 実装ファイルに含めます。また、テスト用の cpp ファイルにもインクルードしていると思います。これにより、ヘッダー ファイルが 2 回インクルードされます。したがって、実際には data0 の 2 つのインスタンスがあります。

コードをデバッグすると、実装ファイルの「data0」が 30 に設定されていることがわかりますが、実際には、テスト ファイルの「data0」は変更されていません。

以下のコードを試してみてください。正しく動作するはずです。

.h
class TestData
{
public:
    TestData(void);
    ~TestData(void);

    int testValue;

    static void Initialize();       
};

extern TestData data0;

//.cpp
TestData data0 = TestData();
TestData::TestData(void){}
TestData::~TestData(void){}

void TestData::Initialize()
{
    data0.testValue = 30;
}

上記のコードは、ヘッダー ファイルで TestData data0 のみを宣言し (extern は、変数が別の場所で定義されていることを意味します)、cpp ファイルで定義します。したがって、この場合、data0 のインスタンスは 1 つだけです。

于 2013-11-14T16:48:35.543 に答える