Dolarun
@Dolarun

Какое связывание у namespace, определённёго в области видимости файла .cpp?

Какое связывание у namespace, определённёго в области видимости файла .cpp?

Например, в таком коде:
#include "header.hpp"
namespace Chrono
{
    Date &Date::add_year(int n)
    {
        if (d == 29 && m == 2 )
        {
            d = 1;
            m = 3;
        }
        y += n;
        return *this;
    }
    void Date::set_default()
    {
        d = 1;
        m = 1;
        y = 1970;
    }
}
  • Вопрос задан
  • 107 просмотров
Решения вопроса 1
@MarkusD Куратор тега C++
все время мелю чепуху :)
Файлы с расширением .cpp обычно являются точками сборки модулей трансляции [?].
Характеристики связывания имеют свой эффект только между модулями трансляции. Компоновщик занимается связыванием кода и работает с результатами обработки именно модулей трансляции - объектными файлами.
Поэтому, если в одном .cpp подключить другой .cpp (исключенный из сборки иными способами), то все элементы с внутренним связыванием любого из этих .cpp будут доступны в них обоих.
Это будет справедливо и для файлов с расширением .h. Файлы .cpp обычно включают .h и все вместе своим кодом формируют модуль трансляции, в котором доступны все элементы с внутренним связыванием. Даже в коде файлов .h.
Это важно учитывать чтобы не совершать некоторых ошибок.

По существу вопроса. Все нестатические (без спецификатора static) элементы именованных пространств имен по умолчанию имеют внешнее связывание [?]. Глобальное пространство является тоже именованным (и доступно через :: без имени слева) и ровно так же наделяет все свои нестатические элементы характеристикой внешнего связывания.

В противоположность этому, абсолютно все элементы анонимных пространств имен (даже элементы вложенных именованных пространств) имеют характеристику внутреннего связывания [?].
Довольно распространенной ошибкой является определение анонимных пространств и статических элементов пространств в заголовках, после чего сразу множество модулей трансляции пополняются кодом с внутренним связыванием. Это приводит к разбуханию бинарного кода и усложнению сборки.

Отдельно хотелось бы обозначить inline.
Спецификатор inline[?] дает пометку слабого внешнего связывания для любой сущности. Что константа или глобальная переменная, что функция или метод (даже статический), помечаются как сущности с внешним связыванием, которое не нарушает ODR в случае если все определения цели связывания во всех модулях трансляции являются полностью одинаковыми. Если хоть одно определение цели связывания отличается - будет нарушение ODR.
Компоновщик подберет самое первое определение и встроит его в бинарный код. После этого компоновщик будет только проверять другие встреченные определения на предмет соответствия первому, а линковку кода будет производить только относительно первого встреченного определения.
Поэтому, если в любом именованном пространстве, в нескольких .cpp определить inline функции с одним именем и одной сигнатурой, но разными телами, то проблем со сборкой будет не избежать.

Все это можно более детально изучить в статье на хабре.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы