0

我有很多必须用 C++ 编写的 C# 代码。我在 C++ 方面没有太多经验。

我正在使用 Visual Studio 2012 进行构建。该项目是 C++ 中的静态库(不在 C++/CLI 中)。

我正在创建一些 UnitTest,在 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;
    }
}

为什么会这样?

更新:

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

当我的测试不起作用时(在类中有 Initialize),调用顺序是:

  1. TestData (data0) 构造函数(地址:1)
  2. TestData (data0) 构造函数(地址:2)
  3. 初始化:使用地址为 1的 data0
  4. 测试:使用带有地址 2的 data0

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

  1. TestData (data0) 构造函数(地址:1)
  2. TestData (data0) 构造函数(地址:2)
  3. 初始化:使用地址为 2的 data0
  4. 测试:使用带有地址 2的 data0

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

4

1 回答 1

1

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

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

您在头文件中定义“静态 TestData data0 = TestData()”,并将其包含在 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 实例。

于 2013-11-14T16:48:35.543 回答