79

I have read in places like here that you have to include .h files and not .cpp files, because otherwise then you get an error. So for example

main.cpp

#include <iostream>
#include "foop.h"

int main(int argc, char *argv[])
{
int x=42;
std::cout << x <<std::endl;
std::cout << foo(x) << std::endl;
return 0;
}

foop.h

#ifndef FOOP_H
#define FOOP_H
int foo(int a);
#endif

foop.cpp

int foo(int a){
    return ++a;
}

works, but if I replace #include "foop.h" with #include "foop.cpp" I get an error (Using Dev C++ 4.9.9.2, Windows):

multiple definition of foo(int)
first defined here

Why is this?

Community
  • 1
  • 1

10 Answers10

76

What include does is copying all the contents from the file (which is the argument inside the <> or the "" ), so when the preproccesor finishes its work main.cpp will look like:

// iostream stuff

int foo(int a){
    return ++a;
}

int main(int argc, char *argv[])
{
   int x=42;
   std::cout << x <<std::endl;
   std::cout << foo(x) << std::endl;
   return 0;
}

So foo will be defined in main.cpp, but a definition also exists in foop.cpp, so the compiler "gets confused" because of the function duplication.

Baum mit Augen
  • 49,044
  • 25
  • 144
  • 182
xorguy
  • 2,594
  • 1
  • 16
  • 14
  • 2
    I suppose you could work around it by using `#pragma once` directives. – chtenb Jan 25 '16 at 12:01
  • 4
    @xorguy how does foop.c and foop.h knows about each other? I understand what you are saying in your answer but it is still unclear to me how does main.cpp knows about definition of foo? main.cpp includes foop.h whare is only declaration not definition of foo. So how does main.cpp knows about definition of foo? – Wakan Tanka Aug 26 '16 at 09:47
  • 1
    @WakanTanka If done the correct way (i.e. including the header file), `main.cpp` does *not* know about `foo.cpp`, and therfore does not throw an error. This is why we use header files. In his answer, @xorguy used an example where `main.cpp` is #including the cpp file instead. In this case, because the same function end up getting defined in both `main.cpp` and `foo.cpp`, an error is thrown. – spicypumpkin Mar 07 '17 at 06:57
  • 1
    Compiler will remain happy, it is linker which will show an error about duplicate implementation. At the same time if you exclude foo.cpp from linking - the build will succeed even without `#pragma once`. But it is waste of compiler time to do this way in big projects, because all code will recompile on any change. – noonex Apr 20 '20 at 08:34
47

There are many reasons to discourage including a .cpp file, but it isn't strictly disallowed. Your example should compile fine.

The problem is probably that you're compiling both main.cpp and foop.cpp, which means two copies of foop.cpp are being linked together. The linker is complaining about the duplication.

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
24

When you say #include "foop.cpp", it is as if you had copied the entire contents of foop.cpp and pasted it into main.cpp.

So when you compile main.cpp, the compiler emits a main.obj that contains the executable code for two functions: main and foo.

When you compile foop.cpp itself, the compiler emits a foop.obj that contains the executable code for function foo.

When you link them together, the compiler sees two definitions for function foo (one from main.obj and the other from foop.obj) and complains that you have multiple definitions.

rob mayoff
  • 375,296
  • 67
  • 796
  • 848
8

This boils down to a difference between definitions and declarations.

  • You can declare functions and variables multiple times, in different translation units, or in the same translation unit. Once you declare a function or a variable, you can use it from that point on.
  • You can define a non-static function or a variable only once in all of your translation units. Defining non-static items more than once causes linker errors.

Headers generally contain declarations; cpp files contain definitions. When you include a file with definitions more than once, you get duplicates during linking.

In your situation one defintion comes from foo.cpp, and the other definition comes from main.cpp, which includes foo.cpp.

Note: if you change foo to be static, you would have no linking errors. Despite the lack of errors, this is not a good thing to do.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • This is almost the answer I was looking for. I'm literally new in C++, so how do I declare a class, for example? Should I use a header file? Then how do I define that class to be used in another files? Sorry for this question, unrelated, but I don't find appropriate help :( –  Feb 02 '17 at 09:40
  • 1
    @TheProHands [Take a look at this article](https://www.gamedev.net/resources/_/technical/general-programming/organizing-code-files-in-c-and-c-r1798). – Sergey Kalinichenko Feb 02 '17 at 09:51
8

You should just include header file(s).

If you include header file, header file automatically finds .cpp file. --> This process is done by LINKER.

Junho Cha
  • 133
  • 1
  • 4
  • 2
    This answer perfectly explains the problem addressed in the question. – pasha Dec 10 '17 at 10:26
  • 3
    @pasha this answer perfectly misses nuances of this topic while being factually wrong at the same time. – enedil Jan 24 '18 at 23:20
  • 2
    @enedil thanks for pointing that out, after spending time on google i agree now, but please do explain why it is, may be i could learn some other things – pasha Jan 25 '18 at 05:05
  • 6
    @pasha I used to read this answer and thought it was right too... It is so wrong and kinda misleading. There is no such "header file find .cpp file" thing. Because only .cpp files get compiled. Header files merely stay there and wait some source files to inlcude them. Check this video to learn more https://www.youtube.com/watch?v=3tIqpEmWMLI – Rick Apr 25 '18 at 10:06
  • @Rick Thanks for the link – pasha Apr 25 '18 at 13:38
2

Because of the One Definition Rule (probably1).

In C++, each non-inline object and function must have exactly one definition within the program. By #includeing the file in which foo(int) is defined (the CPP file), it is defined both in every file where foop.cpp is #included, and in foop.cpp itself (assuming foop.cpp is compiled).

You can make a function inline to override this behavior, but I'm not recommending that here. I have never seen a situation where it is necessary or even desirable to #include a CPP file.

There are situations where it is desireable to include a definition of something. This is specially true when you try to seperate the definition of a template from the declaration of it. In those cases, I name the file HPP rather than CPP to denote the difference.


1: "(probably)" I say probably here because the actual code you've posted should compile without errors, but given the compiler error it seems likely that the code you posted isn't exactly the same as the code you're compiling.

John Dibling
  • 99,718
  • 31
  • 186
  • 324
1

Because your program now contains two copies of the foo function, once inside foo.cpp and once inside main.cpp

Think of #include as an instruction to the compiler to copy/paste the contents of that file into your code, so you'll end up with a processed main.cpp that looks like this

#include <iostream> // actually you'll get the contents of the iostream header here, but I'm not going to include it!
int foo(int a){
    return ++a;
}

int main(int argc, char *argv[])
{
int x=42;
std::cout << x <<std::endl;
std::cout << foo(x) << std::endl;
return 0;
}

and foo.cpp

int foo(int a){
    return ++a;
}

hence the multiple definition error

benjymous
  • 2,102
  • 1
  • 14
  • 21
  • 1
    Inside the `main.cpp`, there is **NO foo() defined** and `foo()` is defined inside the `foop.cpp` file. When we `#include`, why is `foo()` getting included twice when code inside `foop.cpp` is getting pasted inside the `main.cpp` file only **once**? – asn Aug 13 '19 at 11:19
0

So I found that if you are compiling from Visual Studios you just have to exclude the included .cpp file from the final build (that which you are extending from):

Visual Studios: .cpp file > right click > properties > configuration properties > general > excluded from build > yes

I believe you can also exclude the file when compiling from the command line.

Daedric
  • 502
  • 4
  • 23
0

I want to clarify something: including header files is not neccessary to make the linker understand what you want. You can just declare it and it will be linked fine.

main.cpp:

#include <iostream.h>
//not including "foop.cpp"!

int foo(int a);

int main(){
  std::cout << foo(4) << std::endln;
}
  

foop.cpp:

int foo(int a){
  return a++;
}

I don't encourage doing like this, but know that headers are not some magic which you have to follow to make the code compile.

Fizz Areh
  • 87
  • 7
-3

Using ".h" method is better But if you really want to include the .cpp file then make foo(int) static in foo.cpp