学习记录:C++使用宏替换和重载函数增强函数行为

背景

假设我们有一个日志系统,每当函数被调用时,我们希望记录函数的调用信息,包括函数名、文件名、行号和时间戳。通过宏来增强日志记录的功能,使得每次函数调用都能自动记录调试信息。

1. 普通的日志函数

首先,我们编写一个简单的日志记录函数,来模拟日志记录的功能。

#include <iostream>
#include <fstream>
#include <ctime>

void logMessage(const std::string& message) {
    std::ofstream logFile("log.txt", std::ios::app);
    
    // 获取当前时间
    time_t now = time(0);
    tm* localTime = localtime(&now);

    logFile << "[" << 1900 + localTime->tm_year << "-"
            << 1 + localTime->tm_mon << "-"
            << localTime->tm_mday << " "
            << 1 + localTime->tm_hour << ":"
            << 1 + localTime->tm_min << ":"
            << 1 + localTime->tm_sec << "] "
            << message << std::endl;

    logFile.close();
}

在这个例子中,logMessage 函数接受一个日志消息字符串并将其写入到一个 log.txt 文件中,同时还记录了当前的日期和时间戳。

2. 使用宏增强日志功能

为了方便地自动记录每个函数的文件名、行号和函数调用,我们可以通过宏来增强日志记录功能。通过宏,我们可以在调用 logMessage 时自动传递文件名和行号。

2.1 定义宏 LOG

我们定义一个宏 LOG,它会自动将当前的文件名(__FILE__)和行号(__LINE__)作为信息传递给 logMessage 函数。

#define LOG(message) logMessage(message, __FILE__, __LINE__)

这样,每次调用 LOG 宏时,不仅传递日志信息,还会传递文件名和行号。

2.2 修改日志函数以支持文件名和行号

为了支持文件名和行号,我们修改 logMessage 函数,使其能够接受额外的参数并将它们写入日志文件。

void logMessage(const std::string& message, const char* file, int line) {
    std::ofstream logFile("log.txt", std::ios::app);
    
    // 获取当前时间
    time_t now = time(0);
    tm* localTime = localtime(&now);

    logFile << "[" << 1900 + localTime->tm_year << "-"
            << 1 + localTime->tm_mon << "-"
            << localTime->tm_mday << " "
            << 1 + localTime->tm_hour << ":"
            << 1 + localTime->tm_min << ":"
            << 1 + localTime->tm_sec << "] "
            << "In file: " << file << ", line: " << line << " - "
            << message << std::endl;

    logFile.close();
}

这里我们修改了 logMessage 函数,使它可以接收 fileline 这两个额外的参数,并将它们记录到日志中。

3. 使用宏记录日志

现在我们可以在代码中调用 LOG 宏来记录日志,而不需要手动传递文件名和行号。

#include <iostream>
#include <fstream>
#include <ctime>

// 日志记录函数,支持文件名和行号
void logMessage(const std::string& message, const char* file, int line) {
    std::ofstream logFile("log.txt", std::ios::app);
    
    // 获取当前时间
    time_t now = time(0);
    tm* localTime = localtime(&now);

    logFile << "[" << 1900 + localTime->tm_year << "-"
            << 1 + localTime->tm_mon << "-"
            << localTime->tm_mday << " "
            << 1 + localTime->tm_hour << ":"
            << 1 + localTime->tm_min << ":"
            << 1 + localTime->tm_sec << "] "
            << "In file: " << file << ", line: " << line << " - "
            << message << std::endl;

    logFile.close();
}

// 宏定义
#define LOG(message) logMessage(message, __FILE__, __LINE__)

int main() {
    LOG("This is a log message!");
    LOG("Another log entry.");

    return 0;
}
3.1 输出到 log.txt 文件

当我们运行这个程序时,日志文件 log.txt 中的内容可能如下:

[2024-12-10 15:43:20] In file: main.cpp, line: 30 - This is a log message!
[2024-12-10 15:43:20] In file: main.cpp, line: 31 - Another log entry.

4. 如何工作

  1. LOG(message)

    • LOG 将会被预处理器替换为 logMessage(message, __FILE__, __LINE__)__FILE____LINE__ 是编译器提供的预定义宏,它们分别表示当前的文件名和当前的行号。
    • 这样,你不需要手动传递文件名和行号,它们会自动插入。
  2. 日志函数 logMessage

    • logMessage 函数接受三个参数:日志消息、文件名和行号。
    • 在函数内部,我们通过 __FILE____LINE__ 获取到调用 LOG 宏的文件和行号,然后将它们写入到日志文件中。
  3. 使用宏增强功能

    • 在每次调用 LOG 宏时,都会自动记录文件名和行号,这对于调试和跟踪程序的行为非常有用。

5. 总结

  • 宏的作用:通过宏,LOG(message) 替换为 logMessage(message, __FILE__, __LINE__),实现了自动记录调试信息,而不需要手动传递文件名和行号。
  • 代码简洁性:使用宏,可以使得日志记录更简洁,无需每次都显式传递文件名和行号。
  • 灵活性:通过这种方式,你可以轻松地增强日志记录功能,或者替换其他需要增强功能的函数。

这种方法和重载 new 操作符的思想类似:宏替换和函数重载让你能够在不修改函数原始调用的情况下,增强其行为。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值