C++学习:一个简单适用的跨平台Log类(1)
来源:互联网 发布:怎样打开Windows目录 编辑:程序博客网 时间:2024/06/05 17:14
本文开发一个简单适用的日志类Log,讲述C++一些比较好玩的特性,template、策略类、多线程锁、单件、函数可变参数等的方法。涉及的东西比较多,可能一篇写不完。
这里明确定义缺省构造函数,原因是声明了私有的拷贝构造函数和赋值函数,结果缺省构造函数就没了,派生类会出现编译错误,报告NoCopy无缺省构造函数。
对象锁和类锁的不同地方,就是互斥对象,一个是普通成员变量,一个是静态成员变量,大家都知道,静态成员变量是属于类的,不属于对象。关于对象和类的区别,没有搞明白的,可能需要加深理解。简单的举一个例子,比如狗,狗是类,一只叫小白的狗则是一个对象。现在设计一个类,具备对象锁的互斥能力。代码如下:
现在,也许大家已经初步见到这些小class(策略类)的作用,通过简单的组建,就可以使得类型具备一些复杂的特性,而改动地方很小。对于一个严肃的开发人员来说,写超过100行的函数,一般会比较小心谨慎的。同样,对于一个类型来说,同样是如此,把一个类型设计成小儿简单的,也是代码设计的基本功,C++远远不是带class的C。
在开始Log类之前,先讲解几个简单的class,这些class往往比较小,完成单一的功能,利用C++多重继承机制,把这些小类拼装成比较复杂的类。这些小class,称为策略类。枯燥无味的概念不是重点,《C++设计新思维》的第一章有详细讲述。我只show代码,用代码说明。
第一个类是NoCopy,字面意思就是让类不能复制,具体的就是不能通过构造函数和赋值函数来构造对象。要达到这个目的,只需要自定义类型从这个类派生即可。原理就是把拷贝构造函数和赋值函数屏蔽掉,叫编译器编译不过。代码如下:
class NoCopy{
NoCopy( const NoCopy& );//私有NoCopy& operator=( const NoCopy & ); //私有public:NoCopy(void){}//提供缺省的构造函数};
这里明确定义缺省构造函数,原因是声明了私有的拷贝构造函数和赋值函数,结果缺省构造函数就没了,派生类会出现编译错误,报告NoCopy无缺省构造函数。
第二类是一组类,跟多线程有关。多线程环境下,考虑到并发情况,数据的访问要保证互斥,不能破坏掉。一些伪码如下:
class Something{public: bool WriteOp(...) { m_lock.Lock(); ... m_lock.Unlock(); }private: XxxLock m_lock;//互斥对象};为了实现跨平台,所使用的互斥对象,不能依赖具体某个平台,比如win32,而且要求这种加锁机制,由使用者自己决定是否采用。互斥的时候,需要成对使用Lock和Unlock,防止忘记解锁,导致死锁。一个惯用法比较常用,就是利用构造函数和析构函数。首先来看门卫锁,也叫范围锁的类型:
template<typename LockT>class GuardLock{public:GuardLock( const LockT &lock):m_lock( const_cast<LockT&>(lock) ){m_lock.Lock();}~GuardLock(void){m_lock.Unlock();}private:LockT &m_lock;};GuardLock类型并未对所使用的互斥对象进行限制,通过模板参数来指定。这样可以方便实现跨平台。使用方法如下:
CCriticalSection m_cs;//win32的关键代码段GuardLock<CriticalSection> lock;关于锁的类型,在《C++设计新思维》一书中说了主要有三种:
1、空锁,也就是单线程,Lock和Unlock是空操作;
2、对象锁,就是每个对象都有一个互斥对象,加锁针对单个对象;
3、类锁,就是每个类有一个互斥对象,加锁针对类;
三个不同的锁类型,我们可以通过三个小的class来实现,类型只要从这些小class派生,就可以具备不同的加锁保护。首先来看一下空锁的类型定义:
template<class Host>class EmptyLock{public:struct Lock{Lock() {}explicit Lock( const EmptyLock& ) {}//子类是父类的关系是:is a};};上述的模板Host,是指所要定义的派生类。具体的用法,后面再介绍。还有两个类型的锁,定义为:
template<typename Host, typename LockT>class ObjectLock{LockT m_lock;//普通成员public:ObjectLock():m_lock(){}~ObjectLock(){}class Lock;friend class Lock;class Lock : NoCopy//嵌套类{ObjectLock& m_host;public:explicit Lock(const ObjectLock& host): m_host(const_cast<ObjectLock>(host)){m_host.Lock();}~Lock(void){m_host.Unlock();}};};
template <typename Host, typename LockT>class ClassLock{static LockT s_classLock;//静态成员public:class Lock;friend class Lock;class Lock : NoCopy{public:explicit Lock( const ClassLock& ){ClassLock::s_classLock.Lock();}~Lock(void){ClassLock::s_classLock.Unlock();}};};template <typename Host, typename LockT>LockT ClassLock<Host, LockT>::s_classLock;//定义静态成员变量
对象锁和类锁的不同地方,就是互斥对象,一个是普通成员变量,一个是静态成员变量,大家都知道,静态成员变量是属于类的,不属于对象。关于对象和类的区别,没有搞明白的,可能需要加深理解。简单的举一个例子,比如狗,狗是类,一只叫小白的狗则是一个对象。现在设计一个类,具备对象锁的互斥能力。代码如下:
class MyClass : public ObjectLock<MyClass, CCriticalSection>{public: void TestLock(void) { Lock lock(*this);//这里就是调用具体的加锁函数 //other code; }};这里使用win32的关键代码段举例子,使得MyClass就不是模板类了。现在MyClass类就具备了对象锁的特性。如果后续需要改成类锁,就只需要改一下类型的声明即可:
class MyClass : public ClassLock<MyClass, CCriticalSection>{};
现在,也许大家已经初步见到这些小class(策略类)的作用,通过简单的组建,就可以使得类型具备一些复杂的特性,而改动地方很小。对于一个严肃的开发人员来说,写超过100行的函数,一般会比较小心谨慎的。同样,对于一个类型来说,同样是如此,把一个类型设计成小儿简单的,也是代码设计的基本功,C++远远不是带class的C。
说了这么多,还只是Log类一些准备工作,下一篇再来讲述。
- C++学习:一个简单适用的跨平台Log类(1)
- 一个同步日志系统的简单实现 log for c (linux 平台)
- 一个简单适用的DBCP连接池类
- 一个简单实用的log类
- 打印log的一个简单工具类
- log日志:简单的log日志输出(C++)
- linux平台下C语言实现一个简单的httpsever
- 用C++写的一个简单的Log类
- 一个简单的 C++ Log文本输出类
- 一个简单的 C++ Log文本输出类
- 一个小巧的C++Log输出到文件类
- Android关于Log的一个简单封装
- 一个小巧的C++Log输出到文件类 (转)
- 一个写log的函数 log_func.c
- 一个写log的函数 log_func.c .
- Log类的简单使用
- Log类简单的使用
- (转)简单的log
- Webkit中HTML5 Video的实现分析 (四) - 视频加载及播放的时序图
- 自定义java类实现类似spring的依赖注入功能
- ext4 date 汉化
- 开源项目管理软件redmine-什么时候用,怎么用?(二)
- Receiver XXX type for instance message is a forward declaration
- C++学习:一个简单适用的跨平台Log类(1)
- Vim+cscope+ctags+tags阅读源代码
- 我的java笔记(集合)
- 我要录视频-XML(一)
- 面向对象—在线文件管理模块
- flex父子页面数据交互实现(回调函数)
- gen文件无法生成
- C++调用LUA
- 我的程序员之路01