【AVS C++ SDK】Logger源码分析- C++多态

背景
文件名称文件路径
Logger.h/ConsoleLogger.havs-device-sdk/AVSCommon/Utils/include/AVSCommon/Utils/Logger
Logger.cpp/ConsoleLogger.cAVSCommon/Utils/src/Logger
  • 本文只是针对多态这一C++特性在这里的应用,对于其它内容的代码会在Logger完整分析的文章中进行详细说明
源码分析
Logger 基类

Logger.h

class Logger {
public:
...
/**
     * Send a log entry to this Logger.
     *
     * @param level The severity Level to associate with this log entry.
     * @param entry Object used to build the text of this log entry.
     */
    void log(Level level, const LogEntry& entry);
...

   /**
     * Emit a log entry.
     * NOTE: This method must be thread-safe.
     * NOTE: Delays in returning from this method may hold up calls to Logger::log().
     *
     * @param level The severity Level of this log line.
     * @param time The time that the event to log occurred.
     * @param threadMoniker Moniker of the thread that generated the event.
     * @param text The text of the entry to log.
     */
    virtual void emit(
        Level level,
        std::chrono::system_clock::time_point time,
        const char* threadMoniker,
        const char* text) = 0;

上面代码只是摘取了Logger.h 中与本文章需要讲解的多态应用的部分代码.
在Logger.h 的Logger类声明中,将emit修饰为了纯虚函数(在声明后加了代码=0).

Logger.c

...
void Logger::log(Level level, const LogEntry& entry) {
    if (shouldLog(level)) {
        emit(level, std::chrono::system_clock::now(), ThreadMoniker::getThisThreadMoniker().c_str(), entry.c_str());
    }
}
...

而在Logger.c 中,Logger::log 又调用了emit方法. 而emit在Logger中是定义为了虚函数,这样可行?
实际上,在Logger类的声明中将emit修饰为了纯虚函数,代表了Logger类不能直接实例化对象, 需要被子类继承并由子类实现emit方法.

ConsoleLgger子类

ConsoleLgger.h

/**
 * A very simple (e.g. not asynchronous) @c Logger that logs to console.
 *  * Inheriting @c std::ios_base::Init ensures that the standard iostreams objects are properly initialized before @c
 * ConsoleLogger uses them.
 */
class ConsoleLogger
        : public Logger
        , private std::ios_base::Init {
public:
   /**
     * Return the one and only @c ConsoleLogger instance.
     *
     * @return The one and only @c ConsoleLogger instance.
     */
    static std::shared_ptr<Logger> instance();
    ...
    void emit(Level level, std::chrono::system_clock::time_point time, const char* threadMoniker, const char* text)
        override;

在ConsoleLgger的声明中首先继承了Logger基类,也就是在ConsoleLogger中需要实现Logger基类中的emit方法.
在上面截取的代码片段中声明了emit方法,在声明父类中声明的纯虚函数需要注意以下两点:

  • 子类声明父类的纯虚函数,格式和名称要和父类完整一直
  • 在声明后,需要加上override进行修饰,告诉编译器该方法是重写

ConsoleLgger.c

void ConsoleLogger::emit(
    Level level,
    std::chrono::system_clock::time_point time,
    const char* threadMoniker,
    const char* text) {
    if (m_coutMutex) {
        std::lock_guard<std::mutex> lock(*m_coutMutex);
        std::cout << m_logFormatter.format(level, time, threadMoniker, text) << std::endl;
    }
}

在ConsoleLogger.c中实现emit方法.

在Logger.h 还定义以下的内敛函数

/**
 * Inline method to get the function that ACSDK_<LEVEL> macros will send logs to.
 * In this case @c ACSDK_LOG_MODULE was not defined, so logs are sent to the @c Logger returned by
 * @c get<ACSDK_LOG_SINK>Logger().
 */
inline Logger& ACSDK_GET_LOGGER_FUNCTION() {
    static std::shared_ptr<Logger> logger = ACSDK_GET_SINK_LOGGER();
    /*而ACSDK_GET_SINK_LOGGER()实质上是调用了ConsoleLogger中的getConsoleLogger()进行ConsoleLogger对象的获取.*/
    return *logger;
}

上述代码片段展示的是将子类ConsoleLogger的实例化对象赋值给父类Logger定义的指针变量.
而当通过logger调用emit时,实质上调用的子类Logger实现的emit函数.

...
void Logger::log(Level level, const LogEntry& entry) {
    if (shouldLog(level)) {
        emit(level, std::chrono::system_clock::now(), ThreadMoniker::getThisThreadMoniker().c_str(), entry.c_str());
    }
}
...
也就是当调用logger.log,实质上logger::log()中调用的emit实质上是ACSDK_GET_SINK_LOGGER()中获取的实例(子类)中的emit.
而上面展示的过程实质就是C++所说的多态特性,不同的子类赋值给父类定义的指针变量,然后通过父类进行在不同子类实现的虚函数,实现对不同的子类实现虚函数调用,从而实现多态,也就是调用父类中定义的虚函数,会基于赋值的不同子类而实现不同的动作(每一个子类中国的虚函数中实现的内容可能不同).

#### 总结
本文简单描述了下多态在AVS C++ SDK Utils Logger中的应用.多态的应用增加了代码的可拓展想,可以通过父类对子类对象的方法实现调用. 从而实现代码中调用同一个方法而实现不同的效果.


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值