Функция, имеющая версию релиза, встроенную в файл h, и версию отладки, реализованную на cpp

Я поддерживаю унаследованное приложение MFC и вижу образец, точно такой же, как в " Объектно-ориентированном программировании" в книге Windows, где соответствующая часть:

Persview.h

#ifndef _DEBUG  // debug version in persview.cpp
inline CPersDoc* CPersView::GetDocument()
   { return (CPersDoc*)m_pDocument; }
#endif

Persview.cpp

#ifdef _DEBUG
CPersDoc* CPersView::GetDocument() // non-debug version is inline
{
    ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CPersView)));
    return (CPersView*)m_pDocument;
}
#endif //_DEBUG

Я вижу шаблон, широко применяемый, если я ищу его в Интернете, поэтому я предполагаю, что это сгенерированный мастером код.

Мой вопрос: есть ли какое-либо преимущество или другая веская причина для того, чтобы версия релиза была встроена в файл.h и отладка в файле.cpp? Почему бы не поместить оба файла в один файл рядом друг с другом?

2 ответа

Обратите внимание, что книга, которую вы цитируете, была опубликована в 1994 году. C++ тогда сильно отличался, а компилятор Microsoft C++ - нет. На предположение, inline тогда у него была другая семантика, и он дал указание компилятору встроить вызов функции даже в отладочных конфигурациях.

При этом существуют технические причины: компилятор может встроить функцию, только если он видит полное определение. Если вы хотите, чтобы он был встроен в другой модуль компиляции, определение функции должно быть в заголовочном файле. С другой стороны, вы не можете поместить не встроенную функцию в заголовок, потому что это нарушит правило одного определения, если заголовок будет включен в несколько модулей компиляции. В этом случае вы получите ошибки компоновщика.

Если вы хотите избавиться от дублирования кода и при этом получить те же преимущества, вы можете: Просто переместить отладочную версию в заголовок, отметить ее inlineи удалите условия препроцессора. ASSERTничего не компилируется в конфигурации без отладки, и компилятор может (вероятно, будет) встроить вызов функции. Для конфигурации отладки компилятор не выполняет никаких оптимизаций и выдает код для вызова функции. Вызовы функций желательны в конфигурациях отладки, так как они производят более значимые трассировки стека.

Для не отладочной сборки преимущество заключается в том, что заголовочный файл находится именно там, где inline определение функции принадлежит, так что несколько #includeтолько увидеть одно определение этого.

Для отладочной сборки, где функция не встроена, преимущество состоит в том, что вы придерживаетесь соглашения о объявлениях и определениях, которые являются отдельными - определение - это то место, где вы ожидаете его найти.

т.е. вы бы не поместили их вместе в заголовочный файл, потому что это неожиданно, когда нет inlineи вы бы не поместили их вместе в исходный файл, потому что это было бы неправильно, если inline,

Другие вопросы по тегам