В то время как я читал принятый ответ этого вопроса, у меня был следующий вопрос:
Как правило, методы определяются в заголовочных файлах (.hpp
или безотносительно), и реализация в исходных файлах (.cpp
или безотносительно).
Одна из главных причин это - плохая практика, чтобы когда-либо включать "исходный файл" (#include
) та его реализация методов, был бы затем дублирован, приведя к соединению ошибок.
Когда каждый пишет:
#ifndef BRITNEYSPEARS_HPP
#define BRITNEYSPEARS_HPP
class BritneySpears
{
public:
BritneySpears() {}; // Here the constructor has implementation.
};
#endif /* BRITNEYSPEARS_HPP */
Он дает реализацию конструктора (здесь "пустая" реализация, но все еще).
Но почему затем включая этот заголовочный файл многократно (иначе. на файлах другого источника), не генерирует "дублирующееся определение" ошибка во время ссылки?
Инлайн-функции являются исключением из "правила одного определения": разрешается иметь их идентичные реализации в более чем одной единице компиляции. Функции являются встроенными, если они объявлены встроенными
или реализованы внутри определения класса.
Функции-члены с реализацией внутри определения класса рассматриваются как встроенные функции. На встроенные функции не распространяется одно правило определения.
В частности, когда компоновщик видит две встроенные функции с одинаковой сигнатурой, он обрабатывает их, как если бы это одна и та же функция, и просто выбирает одну из них. Это может привести к действительно странным, трудно обнаруживаемым проблемам .
Потому что это «встроенная» функция. Встроенные функции могут быть включены из заголовков сколько угодно раз, и они не вызывают повторяющихся ошибок компоновщика определений.
Компилятор также попытается сделать их встроенными, поэтому в приведенном выше примере компилятор попробует и полностью исключит вызов конструктора.