简体   繁体   中英

Why put function declarations and definitions in separate files?

In codeacademy's lessons on functions, they teach you to use three files if you are going to call functions in your program:

  • the int main() file, which i've found through trial and error is an indispensable part of the program part of a c++ program (i guess...), with a.cpp file extension

  • a header file for DECLARING functions, with a.hpp file extension.

  • a separate file with function DEFINITIONS, with a.cpp file extension

Would it work to both declare and define functions within the header file by itself and simply include them above int main() ? To me having seperate files for declarations and definitions just seems like it would confuse matters in a larger project.

In a large project you often only need type and function declarations, not the definitions. For example in other header files. If all definitions were in the headers, then the combined result of including multiple other headers and their transitive includes would lead to huge compilation units. This significantly hurts compile times since the amount of code the compiler needs to process would explode to orders of magnitudes more than needed. It would also hurt link times since the linker would have more work to do in discarding duplicates included in many more object files.

You also easily run into ODR (One Definition Rule) issues unless everything is marked inline .

In large projects, function declarations may be needed by many files, but the function definition should only be compiled once. It is combined with all the places that need it at link time.

A small C++ program can be (and often is made of) a single translation unit of eg a few thousand lines of C++ code. In that case, you could have a single myprog.cc C++ source files (with several #include -s inside).

But when you work on a larger program, in teams, it is convenient to have several C++ source files.

Some C++ files are generated by another program (this is called metaprogramming or source to source compilation ) and could have a million lines of C++ lines. ANTLR or GNU Bison or TypeScript2Cxx are capable of generating C++ code.

But if you work in a team of people like Alice and Bob, it is convenient to decide that Alice is responsible of alice.cc and Bob is writing bob.cc , and both cooperate on a common header file header.hh which is #include -d in both alice.cc and bob.cc . That header.hh would practically define theAPI of the software project.

Read more about version control systems (I prefer git ) and build automation tools (such as ninja or make ).

Look for inspiration inside the C++ code of existing open source projects on gitlab or github or elsewhere (in particular, inside the source code of Clang and of GCC , both being major C++ compilers).

FWIW, in GCC 10.1 (of may, 2020) the gcc/go/gofrontend/expressions.cc file is handwritten and has 19711 lines of C++ code, so nearly twenty thousands lines. They are compiled daily. I do know the people working on that, they are brilliant and nice professionals. The biggest file of FTLK 1.4 is its src/Fl_Text_Display.cxx with 4175 C++ lines.

By personal experience, you might have a single C++ function of several dozen thousands lines of C++ (this makes practical sense only when that C++ code is generated), but then the compilation time by an optimizing compiler is dissuasive. You could adapt my manydl.c program to generate C++ files (it currently generates "random" C files with functions of "tunable" size) of arbitrary size. But C++ code generated by Fluid or Qt Designer might be quite large, and C++ code generated for GUI is often made of long but conceptually simple functions.

Nothing in the C++11 standard (see n3337 ) requires several translation units. You might have (see sqlite for an example) a single C++ file foo.cc of a million lines. And you could generate some of the C++ source code. The Qt project, the GCC compiler. Jacques Pitrat's book on Artificial Beings: the conscience of a conscious machine ISBN 978-1848211018 explain in many pages why such an approach is worthwhile.

There's kind of two answers to this question

  1. why would YOU the programmer want to split things out into multiple.h/.hpp and.cpp files?

    I believe the answer here is it can help organization when your.cpp files become very large with a lot of code that may not be relevant to someone who needs to provide the functionality provided by the file. Here's an example:

    Let's say you have some c++ code that that display images on a screen. You as the person who wants to use that code are likely interested in the functions/classes exposed by that code which let you control that functionality. Maybe the code exposes the following helpful functions:

    • WriteImageToScreen(int position_x, int position_y)
    • ClearScreen()

    It can be much easier to look through a header file which only tells you what you are allowed to use rather than how all of that is implemented. It's very possible that implementing those two functions so that you can call them requires 1000s of lines of code and a bunch of variables and statements you don't care about. Not having to read that helps you focus on the important part of the code. The pieces you want to interact with.

    I've presented this example as if you were calling someone else's code but the same applies for your own code. As your projects get bigger, it can be convenient to have summaries of what each functionality a file exposes.

    Now that all being said, not everyone agrees this is the correct way to do things or that it is helpful.

  2. why is it necessary for the compiler for things to be split out into multiple.h/.hpp and.cpp files?

    Just in case you aren't familiar with the term, a compiler is the program which turns your source code text into a program which your computer can execute.

    So why does the compiler need separate.hpp/.cpp files? Others have pretty much already hit the nail on the head with this one, but c++ compilers get confused if something is defined multiple times. If you put everything in a header file, then when you include that header in multiple files it will be defined multiple times. So in essence this circles back to the organizational question.

    I have seen programmers who just have a single main file and then all code is included directly to that main file during compilation

#include "SomeFile.cpp"
#include "AnotherFile.cpp"
// ...
#include "SoManyFiles.cpp"

int main()
{
   DoStuff();
}

I believe this is called a monolith build and it's not recommended.

If you have a toy project, you can.

If you have a 1,000,000 lines of code, your build times will be horrid.

C++20 introduces modules, which should make the whole issue go away.

Other languages have tools that can extract an interface from a "module". Hopefully, when C++20 arrives, tools will become available.

The only good reason to split an interface from an implementation is if there are multiple implementations for one interface. Eg VHDL, and will be available in C++20 modules. The pragmatic reasons are compilation speed and legibility.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM