Страницы

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

суббота, 7 декабря 2019 г.

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

#cpp #cpp_faq


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


Ответы

Ответ 1



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

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

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