При таком использовании ключевое слово static
делает связь вашей функции "внутренней".
Это означает, что hello()
отображается только из hello.cpp
, даже если вы объявляете его для других модулей компиляции.
Например, приведенный ниже код вызывает ошибку связи (неразрешенная внешняя ссылка):
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!
}
Так что вы не можете выставить свою функцию таким образом, по определению.
Теперь, если вы объявите свою функцию static
и внедрите ее прямо в заголовочный файл, после удаления кода hello()
из hello.cpp
:
hello.h:
#pragma once
static void hello()
{
std::cout << "hello" << std::endl;
}
В итоге вы получите столько функций hello()
, сколько у вас будет единиц компиляции, включающих этот файл. Попробуйте, включив hello.h
в несколько .cpp
файлов, и возьмите указатель на эту функцию приветствия из каждого из этих файлов. Вы увидите, что их адреса различаются:
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!
}
Теперь измените hello.h
следующим образом, объявив hello()
как inline
вместо static
:
hello.h:
#pragma once
inline void hello()
{
std::cout << "hello" << std::endl;
}
И повторите тот же тест, что и выше: вы увидите, что адрес hello()
теперь тот же, независимо от файла cpp, который включает hello.h
(0x003c13de
, с моей стороны, прямо сейчас). Ваша функция больше не статична, имеет внешнюю связь, уникальна и используется всеми модулями компиляции.
Более подробная информация доступна в этом руководстве .
Одна важная статья, но я предлагаю прочитать ее целиком:
Когда символ имеет внутреннюю связь, он будет виден только внутри
текущий переводческий блок. Не путайте термин, видимый здесь, с
права доступа вроде приватные. Видимость здесь означает, что компоновщик будет
использовать этот символ только при обработке единицы перевода
в котором символ был объявлен, а не позже (как с символами с
внешняя связь). На практике это означает, что когда вы объявляете
символ для внутренней ссылки в заголовочном файле, каждый перевод
блок, в который вы включаете этот файл, получит свою уникальную копию
символ.