宏C++问题 __VA_ARGS__

3

使用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);
    }
}

2
在宏体中,首先将“_format_”放入括号中。 - Federico klez Culloca
3个回答

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 << "}"; }
}

1
如果您能重写您的消息传递,使用operator<<(),或许使用自定义流缓冲的std::ostreams,就不需要变量参数或者丑陋(个人看法)的宏,并且它看起来更像C++而不是C。

1
该宏使得在生产构建中删除代码变得容易。 - Skizz

0

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

为了安全起见,您可以用括号括起来格式(format)(在我看来不是必需的)。


我定义了一组宏,其中包括__FILE__和__LINE__,一个用于错误,一个用于警告等,并将其打印在我的流中:logger << LOG_ERROR << "消息文本" - John Gordon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接