0

我试图更好地了解宏在现代C++ 和 Visual C++ 中的位置(如果有的话),还参考了 Windows 编程库:宏在这些情况下解决了什么问题(如果有)没有就无法解决使用它们?

我记得从这篇博客文章中读到了谷歌浏览器对宏的 WTL 使用(除其他外),它们也在 MFC 中使用 - 这是该博客文章中的一个宏示例,我想用大量的解释如果可能,请详细说明:

// CWindowImpl
BEGIN_MSG_MAP(Edit)
  MSG_WM_CHAR(OnChar)
  MSG_WM_CONTEXTMENU(OnContextMenu)
  MSG_WM_COPY(OnCopy)
  MSG_WM_CUT(OnCut)
  MESSAGE_HANDLER_EX(WM_IME_COMPOSITION, OnImeComposition)
  MSG_WM_KEYDOWN(OnKeyDown)
  MSG_WM_LBUTTONDBLCLK(OnLButtonDblClk)
  MSG_WM_LBUTTONDOWN(OnLButtonDown)
  MSG_WM_LBUTTONUP(OnLButtonUp)
  MSG_WM_MBUTTONDOWN(OnNonLButtonDown)
  MSG_WM_MOUSEMOVE(OnMouseMove)
  MSG_WM_MOUSELEAVE(OnMouseLeave)
  MSG_WM_NCCALCSIZE(OnNCCalcSize)
  MSG_WM_NCPAINT(OnNCPaint)
  MSG_WM_RBUTTONDOWN(OnNonLButtonDown)
  MSG_WM_PASTE(OnPaste)
  MSG_WM_SYSCHAR(OnSysChar)  // WM_SYSxxx == WM_xxx with ALT down
  MSG_WM_SYSKEYDOWN(OnKeyDown)
END_MSG_MAP()

我已经在 MSDN 上阅读了这些与宏有关的 文章,但我也在尝试学习编写或避免宏以及在何处/何时使用它们的最佳实践。

4

3 回答 3

3

所有这些宏都在公共 sdk 头文件中定义,因此您可以根据需要自行阅读它们的作用。基本上这里发生的是你正在使用宏生成一个 WndProc 函数。每个 MSG_WM_* 条目都是一个 case 语句,通过将其参数从 wParam 和 lParam 转换为其原始类型并调用将这些类型作为参数的辅助函数(然后您可以实现)来处理给定的窗口消息(如果合适的话——一些窗口消息有 0 或 1 个参数)。

在我看来,这一切都是废话。你不得不预先编写一堆样板,但作为交换,你使以后的调试变得更加困难。宏在我的现代编程世界中没有太多的位置,除了检查它们是否被定义。做流量控制的宏,或者假设特定的局部变量总是被定义的,等等,让我很不高兴。特别是当我必须调试它们时。

于 2009-03-17T02:26:59.710 回答
3

彼得,你不妨问问 vi 还是 EMACS 是更好的编辑器。(顺便说一下,EMACS。)很多人认为 C 预处理器是一个可怕的想法。其中包括 Stroustrup 和 Jim Gosling。这就是为什么 Java 没有预处理器,并且 Stroustrup 在 C++ 中放入了无数的东西,从const模板到模板,以避免使用预处理器。

还有其他人发现添加新语言很方便,就像在该代码中一样。

如果你阅读原始的 Bourne shell 代码,你会发现它看起来像

IF a == b THEN
   do_something();
   do_more();
ELSE
   do_less();
FI

Steve Bourne 基本上使用宏来赋予它类似 Algol68 的外观(那是当时非常酷的语言。)除了 Steve Bourne 之外的任何人都很难使用它。

然后看看 Obfuscated C 竞赛,其中一些最令人惊叹的混淆利用了#define.

就个人而言,我不太介意,虽然那个例子有点令人生畏(你如何调试它?)但是做那种事情是没有网络的。那里没有多少瓦伦达人。

于 2009-03-17T02:33:09.243 回答
1

(这个问题有点支离破碎,但忽略了 Windows 部分):

X-Macros使用预处理器来避免代码重复。

于 2009-03-17T02:32:05.893 回答