Следует отметить один важный момент: если функция-член определена в заголовочном файле, она должна быть либо внутри тела класса, либо явно помечена как inline
.Другими словами, это просто неправильно делать это в заголовочном файле:
class A {
public:
A();
};
A::A() {
// constructor body
}
Причина в том, что это неправильно, потому что он заставит компилятор включать определение в каждую единицу компиляции, в то время как очевидно, что любая функциядолжны быть определены только один раз.Вот правильные способы сделать то же самое:
class A {
public:
inline A();
};
inline A::A() {
// constructor body
}
Или:
class A {
public:
inline A() { // inline isn't required here, but it's a good style
// constructor body
}
};
В обоих случаях конструктор является встроенным.Единственный правильный способ сделать его обычной функцией вне строки - это определить ее в файле реализации, а не в заголовке.Это самое важное различие между этими двумя подходами.
Теперь стоит отметить, что встраивание - это оптимизация.И как всегда в случае с оптимизацией, их лучше избегать, пока не возникнет необходимость.Среди других проблем, которые может привести к встраиванию, есть проблема совместимости: если вы изменяете тело функции, которая не является встроенной, вам нужно только перекомпилировать модуль, в котором она определена, и все сразу начинают использовать новую реализацию.С помощью встроенных функций вам нужно перекомпилировать каждый блок, который включает соответствующий заголовок, что может быть проблематично, особенно если заголовок используется разными людьми в разных проектах.
Другими словами, используйте регулярные-линейные определения везде, где это возможно, пока не будет доказано, что профилирование вызова конкретной функции является узким местом производительности.Единственное разумное исключение из этого правила - тривиальные сеттеры и геттеры, и даже с ними лучше быть осторожными - однажды они могут стать нетривиальными, и это будет означать много перекомпиляции и нарушения совместимости.