Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should I put many functions into one file? Or, more or less, one function per file?

I love to organize my code, so ideally I want one class per file or, when I have non-member functions, one function per file.

The reasons are:

  1. When I read the code I will always know in what file I should find a certain function or class.

  2. If it's one class or one non-member function per header file, then I won't include a whole mess when I include a header file.

  3. If I make a small change in a function then only that function will have to be recompiled.

However, splitting everything up into many header and many implementation files can considerately slow down compilation. In my project, most functions access a certain number of templated other library functions. So that code will be compiled over and over, once for each implementation file. Compiling my whole project currently takes 45 minutes or so on one machine. There are about 50 object files, and each one uses the same expensive-to-compile headers.

Maybe, is it acceptable to have one class (or non-member function) per header file, but putting the implementations of many or all of these functions into one implementation file, like in the following example?

// foo.h
void foo(int n);

// bar.h
void bar(double d);

// foobar.cpp
#include <vector>
void foo(int n) { std::vector<int> v; ... }
void bar(double d) { std::vector<int> w; ... }

Again, the advantage would be that I can include just the foo function or just the bar function, and compilation of the whole project will be faster because foobar.cpp is one file, so the std::vector<int> (which is just an example here for some other expensive-to-compile templated construction) has to be compiled in only once, as opposed to twice if I compiled a foo.cpp and bar.cpp separately. Of course, my reason (3) above is not valid for this scenario: After just changing foo(){...} I have to recompile the whole, potentially big, file foobar.cpp.

I'm curious what your opinions are!

like image 487
Frank Avatar asked Feb 10 '09 05:02

Frank


2 Answers

IMHO, you should combine items into logical groupings and create your files based on that.

When I'm writing functions, there are often a half a dozen or so that are tightly related to each other. I tend to put them together in a single header and implementation file.

When I write classes, I usually limit myself to one heavyweight class per header and implementation file. I might add in some convenience functions or tiny helper classes.

If I find that an implementation file is thousands of lines long, that's usually a sign that there's too much there and I need to break it up.

like image 98
Mr Fooz Avatar answered Sep 21 '22 23:09

Mr Fooz


One function per file has a technical advantage if you're making a static library (which I guess it's one of the reasons why projects like the Musl-libc project follow this pattern).

Static libraries are linked with object-file granularity and so if you have a static library libfoobar.a composed of*:

 foo.o
     foo1
     foo2
 bar.o
     bar

then if you link the lib for the bar function, the bar.o archive member will get linked but not the foo.o member. If you link for foo1, then the foo.o member will get linked, bringing in the possibly unnecessary foo2 function.

There are possibly other ways of preventing unneeded functions from being linked in (-ffunction-sections -fdata-sections and --gc-sections) but one function per file is probably most reliable.

There's also the middle ground of putting small number of related functions/data-objects in a file. That way the compiler can better optimize intersymbol references compared to -ffunction-sections/-fdata-sections and you still get at least some granularity for static libs.


  • I'm ignoring C++ name mangling here for the sake of simplicity
like image 38
PSkocik Avatar answered Sep 18 '22 23:09

PSkocik