最近在学习MFC,看的教材是《深入浅出MFC》第二版。
在学习到第三章时遇到一个编译错误,提示一个变量未定义,而这个变量是通过复杂的宏定义得来的。所以只好先将源程序进行宏展开,观察宏展开之后的文件,再寻找出现变量未定义的原因。
先给出书中Frame3代码中的一部分:
书上第104页 0030行到0048行
</pre><p><pre name="code" class="cpp">#define RUNTIME_CLASS(class_name) \
(&class_name::class##class_name)
#define DECLARE_DYNAMIC(class_name) \
public: \
static CRuntimeClass class##class_name; \
virtual CRuntimeClass *GetRuntimeClass() const;
#define _IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, wSchema, pfnNew) \
static char lpsz##class_name[] = #class_name; \
CRuntimeClass class_name::class##class_name = { \
lpsz##class_name, sizeof(class_name), wSchema, pfnNew, \
RUNTIME_CLASS(base_class_name), NULL}; \
static AFX_CLASSINIT _init_##class_name(&class_name::class##class_name); \
CRuntimeClass *class_name::GetRuntimeClass() const \
{ return &class_name::class##class_name; } \
#define IMPLEMENT_DYNAMIC(class_name, base_class_name) \
_IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, 0xFFFF, NULL)
在书上107页 第0050到0056行用到了这上面的宏定义
IMPLEMENT_DYNAMIC(CCmdTarget, CObject)
IMPLEMENT_DYNAMIC(CWinThread, CCmdTarget)
IMPLEMENT_DYNAMIC(CWinApp, CWinThread)
IMPLEMENT_DYNAMIC(CWnd, CCmdTarget)
IMPLEMENT_DYNAMIC(CFrameWnd, CWnd)
IMPLEMENT_DYNAMIC(CDocument, CWinThread)
IMPLEMENT_DYNAMIC(CView, CWnd)
当上面的宏展开时,报编译错误“lpszCCmdTarget"未定义 这类的错误。
因为出错的代码在使用宏的地方,所以无法直观的发现问题。所以想到了先得到宏展开后的代码,然后观察这一部分代码,寻找原因。
通过查资料(http://blog.youkuaiyun.com/xiliang_pan/article/details/7718867),找到了生成宏展开文件的方法,也就是”工程-设置-c/c++-预处理器“,在下面工程选项加上/p参数即可。
然后观察生成的.i文件。
发现上面一句 IMPLEMENT_DYNAMIC(CCmdTarget, CObject) 完成宏替换之后就是
static char _lpszCCmdTarget[] = "CCmdTarget";
CRuntimeClass CCmdTarget::classCCmdTarget = { lpszCCmdTarget, sizeof(CCmdTarget), 0xFFFF, 0, (&CObject::classCObject), 0};
static AFX_CLASSINIT _init_CCmdTarget(&CCmdTarget::classCCmdTarget);
CRuntimeClass *CCmdTarget::GetRuntimeClass() const { return &CCmdTarget::classCCmdTarget; }
现在可以清楚第看到问题了:定义的变量是 _lpszCCmdTarge, 而使用的是 lpszCCmdTarge。
发现原因之后,只需修改源文件,将下划线去掉就可以了。
注:本文使用的IDE为VC++6.0