3
votes

command given by terminal:

g++ main.cpp test.cpp

Error message:

/tmp/ccvgRjlI.o: In function `test2()':
test.cpp:(.text+0x0): multiple definition of `test2()'
/tmp/ccGvwiUE.o:main.cpp:(.text+0x0): first defined here
collect2: error: ld returned 1 exit status main.cpp

Source code:

#include "test.hpp"
int main(int argc, char *argv[])
{
    test2();
    return 0;
}

test.hpp

#ifndef _TEST_HPP_
#define _TEST_HPP_

#include <iostream>

void test();
void test2() { std::cerr << "test2" << std::endl; }

#endif

test.cpp

#include "test.hpp"

using std::cerr;
using std::endl;

void test() { cerr << "test" << endl; }

btw the following compiles fine:

g++ main.cpp

4
Add the inline keyword before test2 to get around the one definition rule. - 0x5453
Nothing to do with your problem, but names like _TEST_HPP_ are reserved in C++. Lose the leading underscore. - user2100815
@latedeveloper would TEST_HPP be fine? - lost
@lost Yes, that would be fine. - user2100815

4 Answers

2
votes

The header test.hpp is included in two compilation units. The first one is the compilation unit main.cpp and the second one is the compilation unit test.cpp.

Functions by default have external linkage. This means that functions with the same name and signature denote the same function in different compilation units. They shall be defined once. However in your program the definition of the function test2 is found in two compilation units and the linker does not know what definition of the function to use.

You could declare the function as an inline function. For example

inline void test2() { std::cerr << "test2" << std::endl; }

In this case it may be defined in each compilation unit.

Or you can place in the header only the function declaration as you made with the function test and define it for example in test.cpp.

Another way is to declare the function as having internal linkage. To do this you can define the function in the header either with the keyword static

static void test2() { std::cerr << "test2" << std::endl; }

or place it in unnamed name space

namespace
{
    void test2() { std::cerr << "test2" << std::endl; }
}

In this case each compilation unit will have its own function test2.

1
votes

Since test.hpp file is included both in main.cpp, and test.cpp, there are two implementations of test2 function. So linker produces an error. Move function implementation to the test.cpp file.

1
votes

You get it because you define (implement) the non-static and non-inline function test2 inside the header file, and you include the header file in both source files. That means the function will be defined in both translation units.

0
votes

main.cpp and test.cpp both include test.hpp which declares void test() and defines void test2(). By including test.hpp in two implementation files, you are making two copies of each definition and declaration. You may declare a function as many times as you want but you can only define it once. Move the body of void test2() to a seperate implementation (.cpp) file to resolve the linker error.