为什么我要在类中创建类变量的定义,如果我只在里面使用它们?

时间:2015-10-14 18:56:35

标签: c++ unit-testing visual-studio-2015

尝试创建一个小测试,我遇到了一个问题

#include "stdafx.h"
#include "CppUnitTest.h"
#include "CppUnitTestAssert.h"

using namespace Microsoft::VisualStudio::CppUnitTestFramework;

namespace SprintfTestNamespace
{       
    TEST_CLASS(SprintfTest)
    {
    public:
        static char output[100];
        static const char * expected;

        TEST_METHOD_INITIALIZE(SprintfTestInit)
        {
            memset(output, 0xaa, sizeof output);
            SprintfTest::expected = "";
        }
        static void expect(const char * s)
        {
            expected = s;
        }
        static void given(int charsWritten)
        {
            Assert::AreEqual((int)strlen(expected), charsWritten,
                L"result string length ");
            Assert::AreEqual(expected, output, false,
                L"result string content ");
            Assert::AreEqual((char)0xaa, output[strlen(expected) + 1],
                L"meaning of the first outer char after string");

        }

        TEST_METHOD(NoFormatOperations)
        {
            expect("hey");
            given(sprintf(output, "hey"));
        }
        TEST_METHOD(InsertString)
        {
            expect("Hello World\n");
            given(sprintf(output, "Hello %s\n", "World"));
        }
    };
    char SprintfTest::output[100];      // notice these two lines!
    const char* SprintfTest::expected;
}

如果我删除了两行标记的行,我收到错误LNK2001:

  

未解析的外部符号" public:static char * SprintfTestNamespace :: SprintfTest :: output" (?输出@ SprintfTest @ @@ SprintfTestNamespace 2PADA)

如果我将它们安装到位,一切正常,它可以构建,链接和测试。但是为什么我要在类中定义类变量,如果我只在其中使用它们?

1 个答案:

答案 0 :(得分:2)

你不是在课外宣布他们。你是在课外定义他们。在C ++中,用作左值的对象需要定义,它基本上为该对象保留存储(内存)。对于静态类成员,您可以通过定义此类对象来保留该内存。

您的课程内容只是这些静态成员的非定义声明。为您提供这些声明的定义是您的责任。当您忘记定义您声明的内容时,您会从链接器中获得“未解析的外部符号...”错误,这正是您的情况所发生的。

请注意,为了满足One Definition Rule,这些定义通常应该转到单个实现文件(public IEnumerable<int> Randomize(int count, int seed) { var generator = new Random(seed); return Enumerable.Range(0, 100) .Select(x => new { Value = x, SortOrder = generator.Next() }) .OrderBy(x => x.SortOrder) .Select(x => x.Value) .Take(count); } 文件)。您不应将此类定义放入头文件中。

C ++中唯一的例外是某些类型的静态成员,这些成员在代码中的任何地方都不用作左值,因此无需为这些成员分配内存。