首页 > 解决方案 > 在 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 文件中进行调试是否有任何优势或其他充分理由?为什么不将两者放在同一个文件中呢?

标签: c++mfcconditional-compilationrelease-buildsdebug-build

解决方案


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

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

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


推荐阅读