设置为实例的静态值在从静态方法设置时有效,但不能从类内的静态方法设置



我有很多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 类中初始化方法):

测试失败,并像这样声明初始化方法。当我调试时,我看到正在设置测试值,但是当它到达资产时,它又回到了 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;
    }
}

为什么会这样?

更新:

按照汉斯的建议,我跟踪了正在使用的变量的地址。它帮助我注意到,由于某种原因,TestData 的构造函数被调用了两次。我不知道为什么。我认为可能正在调用自动分配,所以我在构造函数中添加了一个 int 参数,看看会发生什么,似乎它调用了 data0 的构造函数两次。

当我的测试不起作用(在类中初始化)时,调用顺序为:

  1. 测试数据 (data0) 构造函数 (地址: 1)
  2. 测试数据 (data0) 构造函数 (地址: 2)
  3. 初始化:使用地址为 1 的 data0
  4. 测试:将 data0 与地址 2 一起使用

当我的测试工作(在类外初始化)时,调用顺序为:

  1. 测试数据 (data0) 构造函数 (地址: 1)
  2. 测试数据 (data0) 构造函数 (地址: 2)
  3. 初始化:使用 data0 和地址 2
  4. 测试:将 data0 与地址 2 一起使用

现在我明白为什么我的测试失败了。但是我不明白为什么构造函数被调用两次,以及为什么在一种情况下同时使用两个实例,而在另一种情况下只使用第二个实例。

实际上,

我认为问题与初始化函数是在类内部还是外部定义的无关。这是因为全局变量 data0 和函数定义不在同一文件中。

c++ 中的静态构造与全局变量有另一个含义,这意味着该变量仅在当前文件中可见。

您可以在头文件中定义"静态测试数据数据0 = 测试数据()",并将其包含在 cpp 实现文件中。我想您还将其包含在测试 cpp 文件中,这会导致头文件包含两次。所以实际上有两个 data0 实例。

调试代码时,您会看到实现文件中的"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 实例。

最新更新