WikiSort.ru - Не сортированное

ПОИСК ПО САЙТУ | о проекте

Правило одного определения (One Definition Rule, ODR) — один из основных принципов языка программирования C++. Назначение ODR состоит в том, чтобы в программе не могло появиться два или более конфликтующих между собой определения одной и той же сущности (типа данных, переменной, функции, объекта, шаблона). Если это правило соблюдено, программа ведёт себя так, как будто в ней существует только одно, общее определение любой сущности. Нарушение ODR, если оно не будет обнаружено при компиляции и сборке проекта, приводит к непредсказуемому поведению программы.

Причины появления

Синтаксис языка C++ определяет для ряда сущностей необходимость совмещения описания с объявлением, либо дублирование в объявлении описания. Это связано с отсутствием в языке полноценной поддержки модульности, из-за чего на этапе компиляции файла в его тексте (то есть самом тексте компилируемого модуля и текстах всех включённых в него заголовочных файлов) должны содержаться достаточные для компилятора сведения обо всех используемых программных сущностях, определённых в других единицах трансляции. Так, например, для компиляции файла, в котором используется некий класс, необходимо, по меньшей мере, определение самого класса и его публичных свойств и методов, а для использования в файле встраиваемой (inline) функции каждый использующий файл должен включать её полный текст. Ясно, что для обеспечения согласованности программы все такие определения в пределах системы должны быть идентичны. Обычно это обеспечивается тем, что интерфейсная часть единицы трансляции описывается в соответствующем заголовочном файле, который затем подключается везде, где необходимо использовать определённые в ней сущности. Но в действительности ничто не мешает включить в разные компилируемые файлы разные описания одних и тех же элементов программы. Компилятор не сможет обнаружить такую ошибку, так как в момент трансляции он обрабатывает код только одного модуля.

Другая коллизия возможна в случае, когда в программе окажутся два различных определения одного и того же элемента, либо расхождение между внешним объявлением (со спецификатором extern) и фактическим определением того же элемента. Например, если у внешнего объявления функции и её определения окажется различное число параметров, то вызов функции будет некорректным, но компилятор не сможет этого обнаружить, так как в момент работы видит только одну единицу трансляции.

В своей знаменитой книге «Введение в язык C++» Бьёрн Страуструп приводит следующий пример:

 // file1.c:
     int a = 1;
     int b = 1;
     extern int c;
 // file2.c:
     int a;
     extern double b;
     extern int c;

В данном примере 3 ошибки: a определено дважды («int a;» является определением, где начальное значение a не задано), b в описании и определении имеет различные типы, а c описано дважды, но не определено. Эти виды ошибок в C++ не могут быть обнаружены компилятором. В большинстве случаев их обнаруживает компоновщик.

Ограничения, накладываемые на повторные описания и определения программных сущностей в C++, соблюдение которых гарантирует адекватную обработку таких описаний и определений, сведены в описании языка в так называемое «Правило одного определения».

Положения правила

  1. В пределах любой единицы трансляции шаблон, тип данных, функция, или объект не могут иметь более одного определения, хотя могут иметь неограниченное число объявлений. Определение порождает сущность.
  2. В пределах программы (совокупности всех единиц трансляции) внешний объект или внешняя не-inline функция не могут иметь больше одного определения; если объект или функция используются, у каждого из них должно быть строго по единственному определению. Можно объявить объект или функцию, которые не будут использованы в программе, в этом случае не потребуется и их определения. Ни в коем случае не должно быть более одного определения.
  3. Типы, шаблоны и inline-функции (то есть те сущности, у которых определение полностью или частично совмещается с объявлением) могут определяться в более чем одной единице трансляции, но для каждой такой сущности все её определения должны быть идентичны.
  4. Определения объектов и функций, не являющихся внешними, в разных единицах трансляции определяют различные сущности, даже если их имена и типы совпадают. Эти определения беспрепятственно могут различаться.

Некоторые нарушения ODR могут быть найдены компилятором, но большинство из них обнаруживаются только на этапе компоновки.

Дополнительная информация

Данная страница на сайте WikiSort.ru содержит текст со страницы сайта "Википедия".

Если Вы хотите её отредактировать, то можете сделать это на странице редактирования в Википедии.

Если сделанные Вами правки не будут кем-нибудь удалены, то через несколько дней они появятся на сайте WikiSort.ru .




Текст в блоке "Читать" взят с сайта "Википедия" и доступен по лицензии Creative Commons Attribution-ShareAlike; в отдельных случаях могут действовать дополнительные условия.

Другой контент может иметь иную лицензию. Перед использованием материалов сайта WikiSort.ru внимательно изучите правила лицензирования конкретных элементов наполнения сайта.

2019-2024
WikiSort.ru - проект по пересортировке и дополнению контента Википедии