Used that way, the keyword static
makes your function's linkage "internal".
This means hello()
is only visible from hello.cpp
, even if you declare it to other compilation units.
For example, the code below produces a linkage error (unresolved external reference):
hello.cpp:
#include <iostream>
static void hello()
{
std::cout << "hello" << std::endl;
}
hello.h:
#pragma once
void hello(); // OK, it's declared
main.cpp:
#include "hello.h"
void main()
{
hello(); // But ouch, it's not resolved! The linker can't access to the code you wrote in hello.cpp due to the fact hello() is static!
}
So you can't expose your function that way, by definition.
Now, if you declare your function static
and implement it straight in its header file, after having removed hello()
's code from hello.cpp
:
hello.h:
#pragma once
static void hello()
{
std::cout << "hello" << std::endl;
}
You will end up with as many functions hello()
as you have compilations units that include this file. Give a try by including hello.h
in several .cpp
files and take a pointer to this hello function from each of these files. You will see that their addresses differ:
main.cpp:
#include <iostream>
#include "otherFile.h"
void main()
{
void * pf = hello; // Gives 0x01181810 during the test I'm currently doing while writing
tryWithAnotherCppFile();
}
otherFile.h:
#pragma once
void tryWithAnotherCppFile();
otherFile.cpp:
#include "otherFile.h"
#include "hello.h"
void tryWithAnotherCppFile()
{
void * pf = hello; // Here it gives 0x01181d40, which is different!
}
Now, change hello.h
the following way, by declaring hello()
as inline
instead of static
:
hello.h:
#pragma once
inline void hello()
{
std::cout << "hello" << std::endl;
}
And redo the same test as above: you will see that hello()
's address is now the same regardless the cpp file that includes hello.h
(0x003c13de
, on my end, right now). Your function is no longer static, it has an external linkage and is unique and shared among all compilation units.
Further details are available in this tutorial.
One relevant piece, but I suggest reading the whole thing:
When a symbol has internal linkage, it will only be visible within the
current translation unit. Do not confuse the term visible here with
access rights like private. Visibility here means that the linker will
only be able to use this symbol when processing the translation unit
in which the symbol was declared, and not later (as with symbols with
external linkage). In practice, this means that when you declare a
symbol to have internal linkage in a header file, each translation
unit you include this file in will get its own unique copy of that
symbol.