如果我试图在另一个文件中定义一个函数,链接器说它已经被定义(运行 测试)
Linker says a function is already defined if I try to define it in another file (running tests)
我在测试项目中有以下文件:
Test.cpp:
#include "pch.h"
#include "CppUnitTest.h"
#include <iostream>
#include "PrintOne.cpp"
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
namespace PointandVectorCreationTest
{
TEST_CLASS(PointandVectorCreationTest)
{
public:
TEST_METHOD(TestMethod1)
{
std::string expected = "1\n";
std::stringstream buffer;
std::streambuf* sbuf = std::cout.rdbuf(); // Save cout's buffer
std::cout.rdbuf(buffer.rdbuf()); // Redirect cout to the stringstream buffer
int result = printOne();
// When finished, redirect cout to the original buffer
std::cout.rdbuf(sbuf);
std::cout << "std original buffer: \n";
std::cout << buffer.get();
// Test
Assert::AreEqual(expected, buffer.str());
}
};
}
PrintOne.cpp:
#include <iostream>
int printOne() {
std::cout << 1 << std::endl;
return 0;
}
当我在 Visual Studio 中尝试 运行 此测试时,链接器抛出以下错误:
Error LNK2005 "int __cdecl printOne(void)" (?printOne@@YAHXZ) already defined in PrintOne.obj
链接 Test.obj
时抛出此错误。
我没有在 Test.cpp
中的任何地方定义 printOne
。事实上,如果我只是将函数的定义复制到 Test.cpp
并像这样删除 PrintOne.cpp
文件:
Test.cpp:
#include "pch.h"
#include "CppUnitTest.h"
#include <iostream>
int printOne() {
std::cout << 1 << std::endl;
return 0;
}
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
namespace PointandVectorCreationTest
{
TEST_CLASS(PointandVectorCreationTest)
{
public:
TEST_METHOD(TestMethod1)
{
std::string expected = "1\n";
std::stringstream buffer;
std::streambuf* sbuf = std::cout.rdbuf(); // Save cout's buffer
std::cout.rdbuf(buffer.rdbuf()); // Redirect cout to the stringstream buffer
int result = printOne();
// When finished, redirect cout to the original buffer
std::cout.rdbuf(sbuf);
std::cout << "std original buffer: \n";
std::cout << buffer.get();
// Test
Assert::AreEqual(expected, buffer.str());
}
};
}
测试运行很好。我宁愿避免在测试它们的同一个文件中编写我使用的所有函数,所以对我来说这不应该是一个解决方案。
为什么链接器会抛出这个异常?我该如何解决这个问题,以便将我的函数定义与测试文件分开?
I'm not defining printOne
anywhere in Test.cpp
.
其实你是,当你把PrintOne.cpp
的源代码#include
变成Test.cpp
的时候。如果你然后编译 link Test.cpp
和 PrintOne.cpp
在一起,linker 确实看到 printOne()
的 2 个定义,每个 .obj
一个文件。
对于您尝试执行的操作,您需要添加一个 .h
文件,该文件仅 声明 printOne()
,然后您可以 #include
那个文件到两个 .cpp
文件中,其中只有一个 定义 printOne()
,例如:
Test.cpp:
#include "pch.h"
#include "CppUnitTest.h"
#include <iostream>
#include "PrintOne.h"
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
namespace PointandVectorCreationTest
{
TEST_CLASS(PointandVectorCreationTest)
{
public:
TEST_METHOD(TestMethod1)
{
std::string expected = "1\n";
std::stringstream buffer;
std::streambuf* sbuf = std::cout.rdbuf(); // Save cout's buffer
std::cout.rdbuf(buffer.rdbuf()); // Redirect cout to the stringstream buffer
int result = printOne();
// When finished, redirect cout to the original buffer
std::cout.rdbuf(sbuf);
std::cout << "std original buffer: \n";
std::cout << buffer.get();
// Test
Assert::AreEqual(expected, buffer.str());
}
};
}
PrintOne.h
#pragma once
int printOne();
PrintOne.cpp:
#include "PrintOne.h"
#include <iostream>
int printOne() {
std::cout << 1 << std::endl;
return 0;
}
当你的 Test.cpp
文件中有像 #include "PrintOne.cpp"
这样的行时,PrintOne.cpp
的全部内容(包括 printOne()
函数的定义)将是包含在 Test.cpp
的源代码中;因此,Test.obj
文件将包含 printOne()
函数的定义。
如果你的项目中还包含 PrintOne.cpp
文件——从链接器引用 PrintOne.obj
模块这一事实看来——那么也会有 也是该目标文件中 printOne()
函数的定义。
因此,您有多个(虽然相同)函数定义,如链接器所指示的那样。
为避免这种情况,请将包含的 PrintOne.cpp
source 文件替换为提供 declaration (prototype/signature) for the printOne
function (源文件的内容将被添加,无论如何,如果它是项目的一部分。)
一般来说,#include ...
源 (cpp) 文件是不可取的(尽管在某些 情况下它可能有用)。值得一读:
我在测试项目中有以下文件:
Test.cpp:
#include "pch.h"
#include "CppUnitTest.h"
#include <iostream>
#include "PrintOne.cpp"
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
namespace PointandVectorCreationTest
{
TEST_CLASS(PointandVectorCreationTest)
{
public:
TEST_METHOD(TestMethod1)
{
std::string expected = "1\n";
std::stringstream buffer;
std::streambuf* sbuf = std::cout.rdbuf(); // Save cout's buffer
std::cout.rdbuf(buffer.rdbuf()); // Redirect cout to the stringstream buffer
int result = printOne();
// When finished, redirect cout to the original buffer
std::cout.rdbuf(sbuf);
std::cout << "std original buffer: \n";
std::cout << buffer.get();
// Test
Assert::AreEqual(expected, buffer.str());
}
};
}
PrintOne.cpp:
#include <iostream>
int printOne() {
std::cout << 1 << std::endl;
return 0;
}
当我在 Visual Studio 中尝试 运行 此测试时,链接器抛出以下错误:
Error LNK2005 "int __cdecl printOne(void)" (?printOne@@YAHXZ) already defined in PrintOne.obj
链接 Test.obj
时抛出此错误。
我没有在 Test.cpp
中的任何地方定义 printOne
。事实上,如果我只是将函数的定义复制到 Test.cpp
并像这样删除 PrintOne.cpp
文件:
Test.cpp:
#include "pch.h"
#include "CppUnitTest.h"
#include <iostream>
int printOne() {
std::cout << 1 << std::endl;
return 0;
}
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
namespace PointandVectorCreationTest
{
TEST_CLASS(PointandVectorCreationTest)
{
public:
TEST_METHOD(TestMethod1)
{
std::string expected = "1\n";
std::stringstream buffer;
std::streambuf* sbuf = std::cout.rdbuf(); // Save cout's buffer
std::cout.rdbuf(buffer.rdbuf()); // Redirect cout to the stringstream buffer
int result = printOne();
// When finished, redirect cout to the original buffer
std::cout.rdbuf(sbuf);
std::cout << "std original buffer: \n";
std::cout << buffer.get();
// Test
Assert::AreEqual(expected, buffer.str());
}
};
}
测试运行很好。我宁愿避免在测试它们的同一个文件中编写我使用的所有函数,所以对我来说这不应该是一个解决方案。
为什么链接器会抛出这个异常?我该如何解决这个问题,以便将我的函数定义与测试文件分开?
I'm not defining
printOne
anywhere inTest.cpp
.
其实你是,当你把PrintOne.cpp
的源代码#include
变成Test.cpp
的时候。如果你然后编译 link Test.cpp
和 PrintOne.cpp
在一起,linker 确实看到 printOne()
的 2 个定义,每个 .obj
一个文件。
对于您尝试执行的操作,您需要添加一个 .h
文件,该文件仅 声明 printOne()
,然后您可以 #include
那个文件到两个 .cpp
文件中,其中只有一个 定义 printOne()
,例如:
Test.cpp:
#include "pch.h"
#include "CppUnitTest.h"
#include <iostream>
#include "PrintOne.h"
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
namespace PointandVectorCreationTest
{
TEST_CLASS(PointandVectorCreationTest)
{
public:
TEST_METHOD(TestMethod1)
{
std::string expected = "1\n";
std::stringstream buffer;
std::streambuf* sbuf = std::cout.rdbuf(); // Save cout's buffer
std::cout.rdbuf(buffer.rdbuf()); // Redirect cout to the stringstream buffer
int result = printOne();
// When finished, redirect cout to the original buffer
std::cout.rdbuf(sbuf);
std::cout << "std original buffer: \n";
std::cout << buffer.get();
// Test
Assert::AreEqual(expected, buffer.str());
}
};
}
PrintOne.h
#pragma once
int printOne();
PrintOne.cpp:
#include "PrintOne.h"
#include <iostream>
int printOne() {
std::cout << 1 << std::endl;
return 0;
}
当你的 Test.cpp
文件中有像 #include "PrintOne.cpp"
这样的行时,PrintOne.cpp
的全部内容(包括 printOne()
函数的定义)将是包含在 Test.cpp
的源代码中;因此,Test.obj
文件将包含 printOne()
函数的定义。
如果你的项目中还包含 PrintOne.cpp
文件——从链接器引用 PrintOne.obj
模块这一事实看来——那么也会有 也是该目标文件中 printOne()
函数的定义。
因此,您有多个(虽然相同)函数定义,如链接器所指示的那样。
为避免这种情况,请将包含的 PrintOne.cpp
source 文件替换为提供 declaration (prototype/signature) for the printOne
function (源文件的内容将被添加,无论如何,如果它是项目的一部分。)
一般来说,#include ...
源 (cpp) 文件是不可取的(尽管在某些 情况下它可能有用)。值得一读: