尝试创建一个小测试,我遇到了一个问题
#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)
如果我将它们安装到位,一切正常,它可以构建,链接和测试。但是为什么我要在类中定义类变量,如果我只在其中使用它们?
答案 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 ++中唯一的例外是某些类型的静态成员,这些成员在代码中的任何地方都不用作左值,因此无需为这些成员分配内存。