2

I have a header file I want to include in another cpp file. I want to know what is the difference if I write the header file like this,

#include <iostream>
#include <string>
using namespace std;

string ret()
{
return "called";
}

===================================

#include <iostream>
#include <string>
using namespace std;

static string ret()
{
return "called";
}

I can access the ret() function anyway!! So, what's the use of the static?

Blachshma
  • 17,097
  • 4
  • 58
  • 72
Tahlil
  • 2,680
  • 6
  • 43
  • 84
  • 1
    This is a really bad .h for several reasons – Karthik T Jan 08 '13 at 09:01
  • I just wrote it to simplify my question. but what is bad about it? – Tahlil Jan 08 '13 at 09:01
  • 2
    possible duplicate of [What is a "static" function?](http://stackoverflow.com/questions/558122/what-is-a-static-function) – Karthik T Jan 08 '13 at 09:01
  • [Why is 'using namespace std;' considered a bad practice in C++?](http://stackoverflow.com/q/1452721) for why it is bad to put `using namespace std` – Karthik T Jan 08 '13 at 09:02
  • 2
    and the **non static version** will generate `fatal error LNK1169: one or more multiply defined symbols found` if you include this header in more than 1 cpp. This is because the definition of the file is in the header. This means every place that this file is included has a definition, hence the error – Karthik T Jan 08 '13 at 09:04
  • 1
    Which brings us to what static does, with functions, they are not visible outside the cpp file they are defined in. – Karthik T Jan 08 '13 at 09:06

4 Answers4

5

That is a pretty evil header file you're showing.

  1. Never put using namespace std; into a header file. This forces anyone including the header to have all of std in the global namespace.

  2. Use some form of include guards.

  3. static makes the function invisible outside the .cpp where it's included. This means that every .cpp which includes the header will have its own copy of the function. static (non-member) functions should only be used if you specifically need this behaviour.

  4. If you don't use static, you should either move the definition from the header into a source file (if you want it defined once), or declare the function inline (its code will then be inlined on every call site, if possible). If you do neither of these, you'll get multiple definition errors if you include the header in more than one source file.

Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455
  • I'd give this +1 *except* for bullet point 4), which is... wierd? – DevSolar Jan 08 '13 at 09:10
  • @DevSolar Why? The function is defined in the header. If you include it in more than one source file, you'll get a linker error of "mutliply defined symbol `ret`" or some such. – Angew is no longer proud of SO Jan 08 '13 at 09:11
  • 2
    The solution would be *not* defining the function in the header, *or* making it static / putting it in an anonymous namespace if you indeed *want* that kind of behaviour. But declaring it `inline` with the intention of avoiding multiple definition errors is an ugly kludge IMNSHO. You get the code of the function not only in each translation unit, but *at every place it is being called*, i.e. being even worse than having it `static`... – DevSolar Jan 08 '13 at 09:14
  • Fair enough, I'll amend the answer. – Angew is no longer proud of SO Jan 08 '13 at 09:19
  • 1
    @DevSolar: I disagree with your NSHO. You are mistaken in your belief that `inline` has a significant effect on whether the compiler actually inlines the function or not. This has not been the case in mainstream compilers for years -- they all make their own decisions whether to inline functions, and pay little or no attention to `inline` for this purpose. The semantic effect of `inline` is precisely that the function can be defined in multiple TUs. That wasn't its original purpose, but it's the meaning now and it is not a kludge to use that meaning. – Steve Jessop Jan 08 '13 at 09:20
  • @SteveJessop: I am aware that compilers use `inline` as a suggestion at best. (They are still *asked* to do full inlining by the letter of the standard, so you are relying on good sense of the compiler designers when using `inline` and expecting your code to stay small.) I still stand by my opinion that using `inline` to cover up for poor header design (i.e., `#pragma dont_warn_me_about_being_a_bloody_slothful_code_designer`) is being lazy, and the wrong way to go about this. – DevSolar Jan 08 '13 at 09:31
  • @DevSolar: if it were done to cover poor header design then I suppose that would be bad. Anything done to cover poor design is pretty much bad by definition of "poor design". But your apparent belief that an `inline` function in a header is primarily a cover for poor design, is incorrect. It's *the* way to define a shared function in a header (as opposed to `static` / nameless namespaces, which are the ways to define multiple identical functions in a header). – Steve Jessop Jan 08 '13 at 09:33
  • Perhaps the point where we differ is that I think defining a function in a header is a code organization decision to be weighed up as suits the particular circumstance. You seem to think it's slothful (or at least, sufficiently often slothful that it's "weird" and "an ugly kludge" for Angew to even suggest it as an available option). – Steve Jessop Jan 08 '13 at 09:41
  • @SteveJessop: No, we disagree on *both* whether definitions in headers are "OK" (I think they are not, and I bemoan the necessity to do so in case of templates), **and** on whether `inline` is an "OK" way to get around the multiple-definition problem (which I think it's not). But that's just my opinion (albeit stated "not so humbly"), so let's agree to disagree. – DevSolar Jan 08 '13 at 10:10
4

The first header file defines a function called ret with external linkage in every translation unit that includes it. This is incorrect if more than one such TU is linked in the same program.

The second header file defines a function called ret with internal linkage in every translation unit that includes it. This means that each TU has its own private copy of the function (with a different address) no matter how many are linked together.

There are three correct ways to share code using a header file:

  • function with internal linkage (as in your second header, or in C++11 by putting it in a nameless namespace).
  • inline function with external linkage (replace static with inline). The meaning of inline is that although there is only one copy of the function in the program, every TU that uses the function contains its definition.
  • declare the function in the header, and define in it exactly one .cpp file (for example ret.cpp).

In C++03 there was a fourth way:

  • function with external linkage in a nameless namespace

I believe this is still available in C++11, but in C++11 functions in nameless namespaces have internal linkage by default. I'm not aware of any use in C++11 for making a function in a nameless namespace have external linkage. So as far as functions are concerned, nameless namespaces are a nice way of giving the function internal linkage.

Which one you use depends on your needs. The third option means that you can change the definition of the function without re-compiling the calling code, although you'd still need to re-link the executable unless the function is in a dll.

The first two (static or inline) differ in their behaviour if:

  • the function contains static local variables,
  • you compare function pointers to ret taken in different TUs,
  • you examine your executable size or symbol table,
  • the definition of the function is different in different TUs (perhaps due to different #defines), which is forbidden if the function has external linkage but not if internal.

Otherwise they're much the same.

According to the standard, inline is also a hint that the compiler should optimize calls to that function for fast execution (which in practice means, inline the code at the call site). Most compilers ignore this hint most of the time. They will happily inline a static but non-inline function if they assess it to be a good candidate for inlining, and they will happily avoid inlining an inline function if they assess it to be a bad candidate for inlining.

Steve Jessop
  • 273,490
  • 39
  • 460
  • 699
  • +1 This pretty much summarizes well enough to make me delete my answer. – Alok Save Jan 08 '13 at 09:25
  • Can you please explain what do you mean by "external/internal linkage" ? – Tahlil Jan 08 '13 at 09:41
  • @kalkin: I mean the same thing that the C++ standard means. A name with external linkage refers to the same code entity (function or object) no matter what TU it is used in. A name with internal linkage refers to a different code entity in each TU. – Steve Jessop Jan 08 '13 at 09:46
2

Use header guards.

Don't use "using namespace" in header files. (Actually, don't use "using" in header files. Use identifiers fully qualified.)

And use a header for declaring functions, not for defining them. You will want the code for ret() to be present in the resulting executable only once. You achieve this by putting the definition (code) of ret() in a .cpp file. One .cpp file, not multiple ones (by including the definition).

The header file lists the declaration of the function ret() so that other code "knows" that the function exists, which parameter it takes, and what it returns.

DevSolar
  • 67,862
  • 21
  • 134
  • 209
1

If you define c++ methods as static in the header file, each translation unit ( each .cpp file which includes that header file ) will have different versions of those static methods - they will not have the same address space. Hence the size of your program will increase unnecessarily.

Also, just for clarity:

Defining a method as static only in the .cpp file means that the method has static linkage and is only accessible from other methods within the same .cpp file.

HvS
  • 504
  • 1
  • 14
  • 22