目录
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(µSecondsSinceEpoch_);
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;
}