1

I want to use a function that from the "func.h" file in the Wireshark open source project. I need to use the funct() function in multiple .cpp files, but I get the a multiple definition error.

func.h:

    #ifndef func_h
    #define func_h
    #include<string>
    
     void *funct(char *cName)
     {
         std::string name = cName;
         cName+= ".extension";
     }

In the .cpp files I include the func.h:

    #include "func.h"

And call the funct() function from 2 .cpp files:

    funct("program");

What should I do so I don't get the multiple definition error? A workaround is to copy and paste the function defition in every .cpp file and change the function name, but this is ugly.

Many thanks.

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
Alex Seceleanu
  • 505
  • 4
  • 10
  • 6
    Put the definition in its own `.cpp` file, or mark it `inline` in the `.h`. – BoBTFish Jul 01 '21 at 08:28
  • 1
    Declare the function [static](https://stackoverflow.com/questions/572547/what-does-static-mean-in-c) – Jan Gabriel Jul 01 '21 at 08:31
  • @JanGabriel That won't help. `static` only guards a definition from being accessed from other translation units, but here we have definitions in multiple TUs – Yksisarvinen Jul 01 '21 at 08:34
  • I'm not sure if this is the best duplicate, but here's one: [Is it a good practice to define C++ functions inside header files?](https://stackoverflow.com/questions/25274312/is-it-a-good-practice-to-define-c-functions-inside-header-files) – Yksisarvinen Jul 01 '21 at 08:37
  • @Yksisarvinen, you are completely correct and also that is the reason why it would work. The `funct()` is defined in the header and by including the header file in each source file and making it static then each TU gets its own version. For this specific `funct()` it should be fine. – Jan Gabriel Jul 01 '21 at 08:50
  • @JanGabriel I think it still violates One Definition Rule (unless it would be `inline`), if it is, then it's not a good solution. It may work tho. – Yksisarvinen Jul 01 '21 at 09:02
  • Will test with inline. – Alex Seceleanu Jul 01 '21 at 09:03
  • 1
    @Yksisarvinen Actually, it will help. With `static`, yes, we have definitions in multiple TUs. But this does not break the ODR, because each definition defines a separate function. Live demo: https://wandbox.org/permlink/506cFfJKnuMniOrT. – Daniel Langr Jul 01 '21 at 09:11
  • Okay, I see I was mistaken, thanks for clarifying it to me – Yksisarvinen Jul 01 '21 at 09:16

2 Answers2

5

You have two options:

  • You move the implementation of the function in a separate .c/.cpp file, leaving in the header file only the declaration. Then you compile this source file, and link it with the rest of the program. Example:

func.h

#ifndef func_h
#define func_h
#include<string>

void *funct(char *cName);
#endif

func.cpp

#include "func.h"

void *funct(char *cName)
{
    std::string name = cName;
    cName+= ".extension";
}

You compile and link as usual, e.g.

g++ -c -o func.o func.cpp
g++ -c -o main.o main.cpp
g++ -o prog main.o func.o
  • You specify the keyword inline in the definition of the function. This allows appearance of the function in multiple compile units. See this question.
francesco
  • 7,189
  • 7
  • 22
  • 49
  • Hi @AlexSeceleanu if this or any answer has solved your question please consider [accepting it](https://stackoverflow.com/help/someone-answers) by clicking the check-mark. This indicates to the wider community that you've found a solution and gives some reputation to both the answerer and yourself. There is no obligation to do this. – francesco Jul 01 '21 at 12:09
2

func.cpp:

#include "func.h"

void *funct(char *cName)
{
  std::string name = cName;
  cName+= ".extension";
}

func.h:

#ifndef func_h
#define func_h
#include<string>
    
void *funct(char *cName);
#endif

Then in your build script (CMakeLists.txt, or a simple Makefile), compile both .cpp files and link them into one executable.

You may want to put using namespace std; or using std::string; (check the latter syntax; I usually use the former), in which case you don't have to write std::.

Pierre Abbat
  • 485
  • 4
  • 10
  • 7
    Please **don't** recommend `using namespace std;`, it is [widely considered to be a bad practice](https://stackoverflow.com/q/1452721/1171191). – BoBTFish Jul 01 '21 at 08:46