手写muduo之CMake构建、noncopyable、Timestamp、Logger

文章介绍了如何使用CMake构建muduo库,特别关注了noncopyable基类的设计,以确保派生类不可复制。此外,还详细阐述了Logger模块,包括日志级别和输出功能。
摘要由CSDN通过智能技术生成

目录

1.CMakeLists.txt

2.noncopyable.h

3.Timestamp

3.1 Timestamp.h

3.2  Timestamp.cc

4.Logger

4.1 Logger.h

4.2 Logger.cc

 


1.CMakeLists.txt

我们最终的目的是要生成一个名为mymuduo的动态库

cmake_minimum_required(VERSION 2.5)
project(mymuduo)

#mymuduo最终编译成so动态库,设置动态库的路径,放在根目录的lib文件夹下面
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)

#设置调试信息 以及 启动C++11语言标准
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -std=c++11 -fPIC")

#定义参与编译的源代码文件
aux_source_directory(. SRC_LIST)

#编译生成动态库mymuduo
add_library(mymuduo SHARED ${SRC_LIST})

2.noncopyable.h

muduo库中很多类都继承了noncopyable,且是私有继承

看一下源码: 

把拷贝构造函数和赋值函数都delete掉了
默认的构造函数和析构函数
TCPServer的对象可以创建,调用基类的构造函数,基类的构造和析构是保护的,派生类是可以访问的。
基类的拷贝构造函数和赋值函数直接delete掉了,那当我们对TCPServer的对象进行拷贝构造和赋值的时候,肯定要先调用基类部分的拷贝构造和赋值,然后才是派生类的拷贝构造和赋值,但是基类的拷贝构造和赋值已经删掉了,所以说,从noncopyable继承而来的好处是直接让其派生类都不可拷贝构造和赋值。如果没有noncopyable这个基类的话,每一个类的拷贝构造和赋值重载函数都要delete掉,非常复杂,代码不够简洁。

noncopyable.h

#pragma once // 防止头文件被重复包含

/**
 * noncopyable被继承以后,派生类对象可以正常的构造和析构,但是派生类对象无法进行拷贝构造和赋值操作
 */

class noncopyable
{
public:
    noncopyable(const noncopyable&)=delete;
    noncopyable& operator=(const noncopyable&)=delete;
protected:
    noncopyable()=default;
    ~noncopyable()=default;
};

3.Timestamp

打印当前时间

 在这里我们主要实现toString()和now()两个模块

3.1 Timestamp.h

#pragma once

#include <iostream>
#include <string>

class Timestamp
{
public:
    Timestamp();//默认构造
    explicit Timestamp(int64_t microSecondsSinceEpoch);//带参数的构造,带参数的构造函数都加了explicit关键字,避免隐式对象转换
    static Timestamp now();//获取当前时间
    std::string toString() const;//获取当前时间的年月日时分秒的输出

private:
    int64_t microSecondsSinceEpoch_;
};

3.2  Timestamp.cc

#include "Timestamp.h"

#include <time.h>

Timestamp::Timestamp():microSecondsSinceEpoch_(0){}
    
Timestamp::Timestamp(int64_t microSecondsSinceEpoch)
    : microSecondsSinceEpoch_(microSecondsSinceEpoch)
    {}
    
 //通过now获取一个长整型的时间,然后通过tostring转成年月日   
Timestamp Timestamp::now()
{
    return Timestamp(time(NULL));
}

std::string Timestamp::toString() const
{
    char buf[128]={0};
    tm* tm_time=localtime(&microSecondsSinceEpoch_);
    snprintf(buf,128,"%4d/%02d/%02d %02d:%02d:%02d",
        tm_time->tm_year+1900,
        tm_time->tm_mon+1,
        tm_time->tm_mday,
        tm_time->tm_hour,
        tm_time->tm_min,
        tm_time->tm_sec);
    return buf;
}

#include <iostream>
int main()
{
    std::cout<<Timestamp::now().toString()<<std::endl;

    return 0;
}

测试结果: 

4.Logger

日志模块

4.1 Logger.h

#pragma once

#include <string>

#include "noncopyable.h"

//LOG_INFO("%s %d",arg1,arg2)
//##__VA_ARGS__  获取可变参列表的宏
//logmsgFormat:字符串,后面...是可变参的意思
#define LOG_INFO(logmsgFormat, ...)\
do \
{ \
    Logger& logger=Logger::instance(); \
    logger.setLogLevel(INFO); \
    char buf[1024]={0}; \
    snprintf(buf,1024,logmsgFormat,##__VA_ARGS__); \
    logger.log(buf); \
}while(0)

#define LOG_ERROR(logmsgFormat, ...)\
do \
{ \
    Logger& logger=Logger::instance(); \
    logger.setLogLevel(ERROR); \
    char buf[1024]={0}; \
    snprintf(buf,1024,logmsgFormat,##__VA_ARGS__); \
    logger.log(buf); \
}while(0)

#define LOG_FATAL(logmsgFormat, ...)\
do \
{ \
    Logger& logger=Logger::instance(); \
    logger.setLogLevel(FATAL); \
    char buf[1024]={0}; \
    snprintf(buf,1024,logmsgFormat,##__VA_ARGS__); \
    logger.log(buf); \
    exit(-1)\
}while(0)

#ifdef MUDEBUG
#define LOG_DEBUG(logmsgFormat, ...) \
do \
{ \
    Logger& logger=Logger::instance(); \
    logger.setLogLevel(DEBUG); \
    char buf[1024]={0}; \
    snprintf(buf,1024,logmsgFormat,##__VA_ARGS__); \
    logger.log(buf); \
}while(0)
#else
    #define LOG_DEBUG(logmsgFormat, ...)
#endif

/**定义日志的级别  
 * INFO 打印正常的流程信息
 * ERROR 错误,但不影响软件继续向下执行
 * FATAL 毁灭性打击,出现后系统无法向下运行,就要输出关键的日志信息,然后exit
 * DEBUG 调试信息,默认关闭,可以加上一个宏来控制,如果运行程序时加上这个宏,就开启muduo库的调试信息
 */
enum LogLevel
{
    INFO, //普通信息
    ERROR, //错误信息
    FATAL, //core信息
    DEBUG, //调试信息
};

//输出一个日志类
class Logger:noncopyable
{
public:
    //获取日志唯一的实例对象
    static Logger& instance();
    //设置日志级别
    void setLogLevel(int level);
    //写日志
    void log(std::string msg);
private:
    int logLevel_;//后面加_  :1、防止和库中的名字冲突,库中变量名大多在前面加_;2、区分函数内的变量(局部变量)
    Logger(){}
};

4.2 Logger.cc

#include "Logger.h"
#include "Timestamp.h"

#include <iostream>

// 获取日志唯一的实例对象
Logger &Logger::instance()
{
    static Logger logger;
    return logger;
}

// 设置日志级别
void Logger::setLogLevel(int level)
{
    logLevel_ = level;
}

// 写日志  [级别信息] time : msg
void Logger::log(std::string msg)
{
    switch (logLevel_)
    {
    case INFO:
        std::cout << "[INFO]";
        break;
    case ERROR:
        std::cout << "[ERROR]";
        break;
    case FATAL:
        std::cout << "[FATAL]";
        break;
    case DEBUG:
        std::cout << "[DEBUG]";
        break;
    default:
        break;
    }

    //打印时间和msg
    std::cout<<Timestamp::now().toString()<<":"<<msg<<std::endl;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值