When it comes to functions (non-member functions in C++), marking them as static gives them internal linkage. This means that they are not visible outside the translation unit. Why isn't this the default? I don't have a good statistic but from what I've seen most functions in implementation files should be marked as static.
I believe the consensus is to split functionality into smaller units. So it makes sense that in general the number of "utility"-like functions in the implementation file that should not be visible in other translation units is greater than the number of functions that just are an implementation of the public interface.
What is the reason as to why they went with "export everything" by default in this context?
In the C/C++ compilation model, the preprocessor runs before everything else, and replaces #includes with their contents.
Hence, there's no difference between a function that's defined in a .cpp file and a function defined in a header it includes.
Your suggestion would make functions defined in headers static by default (which would remove the "mulitple definition" linking error), which would be very bad, as it would cause silent code duplication in the resulting binary if you forget inline (in C++) or if you don't know you're not supposed to define functions in headers (in C).
C part
C is now a very old language (from the 1970s...) and is highly conservative. Include files are just meant to be included at the source level. Draft n1570 for C11 explicitly says:
A source file together with all the headers and source files included via the preprocessing directive #include is known as a preprocessing translation unit. After preprocessing, a preprocessing translation unit is called a translation unit.
That means that a conformant C compiler does not make any difference between what comes from an include and a source file, since the inclusion occurred before the compilation phase.
This is enough for functions to receive an external linkage by default (not being declared as static).
C++ part
Despite being a totally different language, C++ still assumes its inheritance from C. Specifically, the C standard library is still officially a part of the C++ standard library.
This is probably enough for non-member function to receive the same processing by default as what they receive in C. This is of course far less important that in the C language, because C functions are actually declared as extern C. But on the other hand, non-member functions are also called namespace scoped function for a reason. And in C++, scoping is the correct way to handle the namespace pollution.
My opinion is that best practices should recommend to scope everything. You just use a named scope to get an external linkage and an anonymous one to limit scoping to the local unit. That is enough to not require changing the C default for non-member functions.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With