Функция, имеющая версию релиза, встроенную в файл 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
,