利用重载处理C++函数可变参数的一个可靠方式

提供与日志消息格式化相关的两个函数:

void LogEvent::format(const char* fmt, ...) {
    va_list al;
    va_start(al, fmt);
    format(fmt, al);
    va_end(al);
}

这个format函数是LogEvent类的成员函数,它设计为接受一个格式化字符串和随后的可变数量的参数(如printf函数)。它是一个可变参数函数,这由参数列表中的省略号(...)表示。

  • va_list al; 声明了一个名为al的变量,类型为va_list,该变量将保存参数列表。
  • va_start(al, fmt); 将al初始化,使其指向参数fmt之后的第一个可变参数。
  • format(fmt, al); 调用了重载版本的format函数,该函数的第二个参数是va_list类型。
  • va_end(al); 清理了与al相关的资源。
void LogEvent::format(const char* fmt, va_list al) {
    char* buf = nullptr;
    int len = vasprintf(&buf, fmt, al);
    if(len != -1) {
        m_ss << std::string(buf, len);
        free(buf);
    }
}

这个重载的format函数与第一个函数紧密相关,但它直接接受一个va_list参数。这个函数是实际执行字符串格式化的地方。

  • char* buf = nullptr; 定义了一个指向字符的指针buf,并将其初始化为nullptr
  • int len = vasprintf(&buf, fmt, al); 使用vasprintf函数根据格式化字符串fmt和参数列表al来分配足够的内存,并写入格式化后的字符串。vasprintf函数返回写入的字符数(不包括结尾的空字符)。
  • 如果len不是-1,代表格式化成功,然后创建一个std::string对象并将其内容添加到LogEvent类内部的字符串流m_ss中。
  • free(buf); 释放vasprintf函数分配的内存。

以下是如何使用这个函数的示例:

Logger::ptr logger = LoggerMgr::GetInstance()->getLogger("system");
// 假设 LogEvent 类和 LoggerMgr 类已经定义好了

LogEvent::ptr event(new LogEvent(logger, LogLevel::INFO, __FILE__, __LINE__, 0, GetThreadId(), GetFiberId(), time(nullptr), "main"));
// 创建日志事件实例

event->format("This is a formatted number: %d, and a string: %s", 42, "hello world");
// 使用 format 方法添加格式化信息

在这个示例中,format 方法使用类似于 C 标准库中 printf 函数的语法,接受一个格式化字符串和一系列可变参数。它会根据格式化字符串和提供的参数来构建最终的日志消息。

它的底层实现逻辑是:

第一个format函数接受一个格式化字符串fmt,随后是一个可变数量的参数,这与printf函数的使用方式类似。这个函数的目的是为了直接被调用时提供方便,允许在代码中直接传入多个参数,并按照fmt指定的格式将它们格式化为字符串。

第二个format函数接受相同的格式化字符串fmt,但第二个参数是va_list类型,它代表一个已经初始化的可变参数列表。这个函数通常用在你已经有一个va_list的情况下,或者当你需要将参数列表传递给另一个函数进行格式化。在这个函数内部,它使用va_startva_end宏来处理可变参数列表,并将这个列表传递给第二个format函数。

使用第一个format函数进行可变参数列表的初始化和清理,第二个format函数提供了更多的灵活性,但是需要手动处理va_list的生命周期,包括它的初始化和清理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值