在h文件上内联发布版本并在cpp上实现调试版本的函数

Function having release version inline on h file and debug version implemented on cpp

本文关键字:版本 cpp 调试 函数 实现 文件 布版本      更新时间:2023-10-16

我正在维护一个遗留的MFC应用程序,我看到的模式与Windows书下的面向对象编程模式完全相同,其中相关部分是:

佩尔维尤·

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

佩尔维尤.cpp

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

如果我在 Internet 上搜索它,我会看到该模式被广泛应用,因此我认为它是向导生成的代码。

我的问题是:发布版本内联在 .h 文件上并在 .cpp 文件上进行调试是否有任何优势或其他充分的理由?为什么不将两者放在同一个文件上,彼此相邻?

请注意,您引用的书是1994年出版的。当时C++非常不同,Microsoft的C++编译器则不是。猜测,inline当时有不同的语义,并指示编译器内联函数调用,即使在调试配置中也是如此。

除此之外,还有技术原因:编译器只有在看到完整定义的情况下才能内联函数。如果希望它内联在不同的编译单元中,则函数定义需要位于头文件中。另一方面,不能将非内联函数放在标头中,因为如果标头包含在多个编译单元中,这将违反一个定义规则。在这种情况下,您会收到链接器错误。

如果您希望摆脱代码重复并仍然获得相同的好处,您可以:只需将调试版本移动到标头中,将其标记为inline,然后删除预处理器条件。ASSERT在非调试配置中编译为无,编译器可以(可能(内联函数调用。对于调试配置,编译器不会执行任何优化,而是发出函数调用的代码。函数调用在调试配置中是可取的,因为它们会产生更有意义的堆栈跟踪。

对于非调试构建,优点是头文件恰好是inline函数定义所属的位置,因此多个#include只能看到它的一个定义。

对于函数未内联的调试版本,优点是您可以保持声明和定义的约定是分开的 - 定义是您希望找到它的位置。

即您不会将它们放在头文件中,因为这在不inline时是意外的,并且您不会将它们放在源文件中,因为当它inline时会出错。