Страницы

Поиск по вопросам

пятница, 2 ноября 2018 г.

Что такое внутреннее и внешнее связывание?

Что такое внутреннее и внешнее связывание в языке C++ ?


Ответ

Стандарт C++:
When a name has external linkage , the entity it denotes can be referred to by names from scopes of other translation units or from other scopes of the same translation unit
и
When a name has internal linkage , the entity it denotes can be referred to by names from other scopes in the same translation unit.
По-русски это можно перевести как: внешнее связывание имеют те сущности, к которым можно обратиться в единице трансляции, отличной от той, где они определены. Например, имея в заголовке header.h:
extern int object;
в first.cpp
int object; ... object = 5;
в second.cpp
#include "header.h" ... object = 3;
Так вот, int object; в first.cpp имеет внешнее связывание, т.е. на него могут ссылаться другие единицы трансляции, что и делает second.cpp. Но чтобы second.cpp узнал, что такая переменная вообще существует, мы ему сказали через extern int object;. Таким образом получается, что несколько единиц трансляции обращаются к одному и тому же объекту в памяти. Это и есть внешнее связывание
Внутренее связывание отличается от внешнего тем, что к сущности имеющей внутренее связывание нельзя обратиться из единицы трансляции, отличной от той, где она определена. Так, если взять тот же пример, но изменить first.cpp на
static int object;
или на
namespace { int object; }
и не трогать другой код то при линковке second.cpp мы получим ошибку линковщика, говорящую, что он не может найти object. Это происходит потому, что object имеет внутреннее связывание и, как я уже сказал, это значит, что другие единицы трансляции не могут видеть это имя.

Для лучшего понимания, можно воспользоваться следующей аналогией: у классов, в C++, есть несколько уровней доступа, в числе которых есть private и public. Компилятор проверяет, чтобы только внутренние части класса(опустим friend'ов и хаки) обращались к private членам, и любое обращение к таковым извне класса вызовет ошибку компиляции. С другой стороны, public члены доступны всем вокруг,— к ним может обращаться любая внешняя сущность.
Так вот, внутреннее и внешнее связывание ведут себя как private и public у классов, только ошибки тут выявляются на этапе линковки, а не компиляции. Другими словами, это ещё можно сказать так: сущности с внешним связыванием экспортируется за пределы единицы трансляции, тогда как с внутренним связыванием — нет, о них внешний мир вообще не знает.

Комментариев нет:

Отправить комментарий