Что такое внутреннее и внешнее связывание в языке 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 у классов, только ошибки тут выявляются на этапе линковки, а не компиляции. Другими словами, это ещё можно сказать так: сущности с внешним связыванием экспортируется за пределы единицы трансляции, тогда как с внутренним связыванием — нет, о них внешний мир вообще не знает.
Комментариев нет:
Отправить комментарий