[БЕЗ_ЗВУКА] Когда мы с вами вводили понятия объявления и определения, мы говорили, что объявлений может быть сколько угодно, а определение обязательно должно быть ровно одно. И давайте мы ещё раз это продемонстрируем: вот у нас есть функция, например, GetSynonymCount, и у неё есть определение в файле synonyms.cpp. Если мы просто возьмём и скопируем это определение, а потом запустим компиляцию, то мы получим ошибку redefinition, уже нам знакомую. Вот мы видим redefinition of GetSynonymCount. Но эта ситуация достаточно простая, понятная: мы два раза в одном файле определили одну и ту же функцию, и компилятор нам об этом сообщил. Однако в больших проектах бывают ситуации, когда в вашем проекте, вроде бы, есть всего одно определение функции, но при этом компилятор сообщает вам, что у вас одна и та же функция определена несколько раз. И давайте посмотрим, как это выглядит и по какой причине случается. Давайте, например, возьмём вот эту нашу функцию GetSynonymCount и перенесём её определение обратно в заголовочный файл, как было у нас несколькими видео ранее. И скомпилируем наш проект. Давайте мы его соберём. Ну вот он, значит, у нас собирается. И что-то пошло не так. Нам компилятор написал first defined here. Это всё, что мы видим в консоли ошибок, во вкладке ошибок. Давайте посмотрим консоль. И здесь, наверное, мы получим чуть больше информации. Вот такое сообщение нам выдал компилятор: multiple definition of GetSynonymCount. И при этом он говорит, что она объявлена в synonyms — определена, defined, в synonyms.h в 18-й строке, вот здесь. И вот, собственно, это то, о чём я говорил, что вот оно у нас, одно определение функции. Мы в одном месте определили, она ни в каком другом файле не определена, но компилятор настойчиво нам утверждает, что определений-то у нас, на самом деле, несколько. И давайте посмотрим, как такое получилось. Для этого ещё раз откроем консоль и внимательно посмотрим на строки запуска компилятора. Мы видим, что их здесь четыре, то есть наши три cpp файла. У нас есть, значит, несколько cpp файлов, и они были успешно скомпилированы, а ошибка выпала на этапе компоновки. Вот мы видим: запускается g++ −o coursera.exe, и ему передаются четыре объектных файла, выполняется их компоновка, и на этапе компоновки у нас возникает ошибка Multiple Definitions. То есть компиляция прошла успешно, каждый cpp файл, который есть в нашем проекте, успешно скомпилировался, а вот когда выполняется компоновка, у нас возник вдруг Multiple Definition. И давайте посмотрим, почему такое происходит. Для этого давайте посмотрим на схему того, как компилируется и собирается наш проект. У нас есть файл synonyms.h, и в нем определена функция GetSynonymCount. Этот файл включается в файл synonyms.cpp с помощью директивы Include, и synonyms.cpp компилируется, в результате чего получается объектный файл. Дальше файл synonyms.h точно так же включается в файл coursera.cpp, и этот файл также компилируется. У нас получается два объектных файла, в каждом из которых есть определение функции GetSynonymCount. Эти два объектных файла поступают на вход компоновщику — он на схеме обозначен синим прямоугольником и назван Linker. Компоновщик берёт два объектных файла и видит, что у него здесь есть определение и здесь есть определение, их два, он не забивает себе голову тем, чтобы убедиться, что они идентичны, он просто видит, что у него одна и та же функция определена в двух объектных файлах, и сообщает нам об ошибке. Вот именно таким образом возникает ошибка Multiple Definition, хотя кажется на первый взгляд, что мы функцию-то определили всего один раз. И как её избежать? Ну собственно, обратным образом, как мы ее создали: вернуть определение функции GetSynonymCount в cpp файл. Вот мы это сделали, запускаем сборку, и у нас проект успешно собирается. А теперь давайте вспомним, что основной мотивацией, основной причиной переноса определений функции и методов классов в cpp файлы у нас было ускорение сборки: мы добивались того, чтобы при повторных сборках у нас перекомпилировались только те файлы, которые действительно изменились. Теперь мы знаем другую, даже более вескую причину помещать определение функции членов классов в cpp файлы: потому что это позволяет нам избежать ошибки Multiple Definitions. Давайте подведем итоги: в этом видео мы с вами узнали, что в C++ есть так называемое правило одного определения, или One Definition Rule. Если функция определена в заголовочном файле, который подключается более чем в один cpp файл, то вот это правило одного определения нарушается, потому что это определение из заголовочного файла попадает в несколько объектных файлов, и чтобы не нарушать One Definition Rule, нужно все определения помещать в cpp файлы.