I have the following files in a testing project:
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;
}
When I try to run this test in Visual Studio, the linker throws the following error:
Error LNK2005 "int __cdecl printOne(void)" (?printOne@@YAHXZ) already defined in PrintOne.obj
This error is thrown when linking Test.obj
.
I'm not defining printOne
anywhere in Test.cpp
. In fact, if I just copy the definition of the function to Test.cpp
and eliminate the PrintOne.cpp
file like so:
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());
}
};
}
The test runs just fine. I'd rather avoid writing all the functions I use in the same file I test them, so to me this shouldn't be a solution.
Why does the linker throw this exception? How can I fix this so I can keep my function definitions separate from the testing file?
CodePudding user response:
I'm not defining
printOne
anywhere inTest.cpp
.
Actually, you are, when you #include
the source code of PrintOne.cpp
into Test.cpp
. If you then compile and link both Test.cpp
and PrintOne.cpp
together, the linker indeed sees 2 definitions of printOne()
, one in each .obj
file.
For what you are attempting to do, you need to add a .h
file that just declares printOne()
, and then you can #include
that file into both .cpp
files, where only one of them defines printOne()
, eg:
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;
}
CodePudding user response:
When you have a line like #include "PrintOne.cpp"
in your Test.cpp
file, then the entire contents of PrintOne.cpp
(including the definition of the printOne()
function) will be included in Test.cpp
's source code; thus, the Test.obj
file will contain a definition of the printOne()
function.
If you then also have the PrintOne.cpp
file included in your project - as it seems from the fact that the linker is referencing a PrintOne.obj
module - then there will also be a definition of the printOne()
function in that object file, too.
So, you have multiple (though identical) definitions of the function, as signalled by the linker.
To avoid this, replace the inclusion of the PrintOne.cpp
source file with one for a header (say #include "PrintOne.h"
) that provides a declaration (prototype/signature) for the printOne
function (The contents of the source file will be added, anyway, if it is part of the project.)
Generally, it is not advisable to #include ...
source (cpp) files (though there are some circumstances where it can be useful). Worth reading: When do I need to #include .cpp files?