【问题标题】:Macro C++ Issues __VA_ARGS__宏 C++ 问题 __VA_ARGS__
【发布时间】:2010-04-30 13:51:12
【问题描述】:

像这样使用 C++ 宏有哪些潜在问题(如果有的话)? 内联函数会是更合适的解决方案吗?

#define EVENT_INFO(_format_, ...) CMyEvent::Generate(__FILE__, __LINE__, CMyEvent::EVT_HIGH, _format_, __VA_ARGS__)

void
CMyEvent::Generate(
    const char* file,                      // filename
    int line,                              // line number
    CMyEvent::LEVEL level,                 // severity level
    const char *format,                    // format of the msg / data
    ...)                                   // variable arguments
{
    // Get a message from the pool
    CMyEvent* p_msg = GetMessageFromPool();
    if(p_msg != NULL)
    {
        va_list arguments; // points to each unnamed argument
        va_start(arguments, format);
        // Fill the object with strings and data.
        p_msg->Fill(file, line, level, 0, format, arguments);
        va_end(arguments);
    }
}

【问题讨论】:

  • 首先将_format_放入宏体的括号中

标签: c++ macros


【解决方案1】:

当您使用 C++ 时,您可以避免使用易受许多问题影响的可变参数列表的陷阱:

  • 不检查参数数量
  • 不检查参数类型

要使其更像 C++,请执行以下操作:

#define EVENT_INFO(args) EventLogStream (__FILE__, __LINE__, __PRETTY_FUNCTION__) << args

然后像这样调用它(警告:这里的所有代码都是伪代码,可能在语法上不正确,但你应该明白基本的想法):

EVENT_INFO ("The answer to " << the_question << " is " << answer); // usually 42

EventLogStream 类似于 cout 对象,和 cout 一样,您可以提供特定于类的输出:

class Vector3D
{
   EventLogStream &operator << (EventLogStream &out) { out << "{" << x << ", " << y << ", " << z << "}"; }
}

【讨论】:

    【解决方案2】:

    如果你可以重写你的消息以使用 operator

    【讨论】:

    • 该宏可以轻松删除生产版本的代码。
    【解决方案3】:

    可变参数宏非常适合用于日志记录。比使用 iostreams 好得多。除非您愿意手动传递__FILE____LINE__,否则内联函数将不起作用。

    为了安全起见,您可以将 format 括在括号中(恕我直言,这不是必需的)

    【讨论】:

    • 我定义了一组宏,包括 FILELINE,一个用于错误,一个用于警告等,并在我的流中打印: logger
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-06-05
    • 2012-08-01
    • 2014-03-19
    • 1970-01-01
    • 2021-09-09
    • 2014-09-01
    • 2013-10-26
    相关资源
    最近更新 更多