首先本文并不是讲解C++萃取技术,关于C++的萃取技术网上有很多文章,推荐http://www.cppblog.com/woaidongmao/archive/2008/11/09/66387.html如果这篇文章能看懂肯定也能看懂我这篇小博文了。

熟悉C++的人肯定都用过auto_ptr这个智能指针,其原理就是在auto_ptr构造的时候将申请到的内存地址放进该对象的内部保存,而这个对象析构的时候则调用delete释放之前申请的内存,这样不仅仅省去了程序员时刻关注何时释放内存的顾忌,同时即使是程序在new和delete中间发生异常被捕获内存仍然会释放不会有泄漏。同时也可以做引申,可以自己写一个类,里面保存临界区对象,当对象创建时进入临界区,而对象析构的时候自从释放临界区,这样也可以保证进临界区和出临界区中间发生异常后锁仍然会释放,在一部分情况下保证程序不会有太大的异常。相关伪代码如下:

 class CAutoLock
{
public:
CAutoLock(LPCRITICAL_SECTION lpCriticalSection)
{
m_lpCriticalSection = lpCriticalSection;
EnterCriticalSection(m_lpCriticalSection);
}
~CAutoLock(){LeaveCriticalSection(m_lpCriticalSection); }
private:
LPCRITICAL_SECTION m_lpCriticalSection;
};

好了,锁和智能指针都有了,但是如果想类似让一个文件句柄HANDLE一样在遇到return时关闭掉,该怎么做呢?其实自己实现一个类似auto_ptr,将内存地址换成文件句柄就可以了,但是如果又遇到一个SOCKET呢?其实可以用模板偏特化搞定。但是我现在介绍一种利用C++萃取技术,用一个主体类再加上一些辅助类完成以上功能。其原理也很简单,利用C++萃取技术,自动识别需要释放的数据类型,然后根据不同的数据类型选择不同的释放方式。相关代码如下:

 #pragma once
#include <windows.h>
#include <Winsock2.h> #pragma comment(lib,"Ws2_32.lib") /*************************************************
示例程序能够识别的类型:
第一为基础句柄(为用CloseHandle释放的)
第二个为网络通信SOCKET,需要用closesocket释放
可以根据实际需要自己添加实现,例子程序就只实现这两个功能
*************************************************/ //基础句柄类(CloseHandle释放类型)
class CCommomHandleObject
{
public:
void clear(HANDLE hCommhandle)
{
if (INVALID_HANDLE_VALUE != hCommhandle)
{
CloseHandle(hCommhandle);
}
}
}; //套接字类(closesocket释放类型)
class CSOCKETObject
{
public:
void clear(SOCKET m_hSocket)
{
if (INVALID_SOCKET != m_hSocket)
{
closesocket(m_hSocket);
}
}
}; //C++萃取基础类
template<class _xTypeShow>
class CTraitsBaseObject
{
}; //根据HANDLE识别出CCommomHandleObject类
template<>
class CTraitsBaseObject<HANDLE>
{
public:
typedef CCommomHandleObject _data_type_show;
}; //根据SOCKET识别出CSOCKETObject
template<>
class CTraitsBaseObject<SOCKET>
{
public:
typedef CSOCKETObject _data_type_show;
};
/****************************************************************************
资源释放类,本例的重点,需要根据每个须释放的资源绑定一个CContainerClass对象
然后对象析构时会根据CTraitsBaseObject<_xType>::_data_type_show识别出是否为
自己认识的数据类型,如不认识则直接报错,然后创建临时对象调用clear,
根据实际情况销毁绑定的资源。
****************************************************************************/
template<class _xType>
class CContainerClass
{
public:
CContainerClass(_xType &_tay ){m_hTay = _tay;}
~CContainerClass(void){clear();}
private:
CContainerClass(){}
CContainerClass(CContainerClass &tay){} void clear()
{
CTraitsBaseObject<_xType>::_data_type_show().clear(m_hTay);
}
private:
_xType m_hTay;
};

以上代码只是完成了需要用CloseHandle释放的句柄和SOCKET两种资源类型,需要增加时只需增加相信的类型即可。而资源申请后创建一个CContainerClass对象,选择对应的类型将两者绑定即可。实际应用代码如下:

 int _tmain(int argc, _TCHAR* argv[])
{
HANDLE hFileFile = CreateFile(_T("D:\\Program Files\\小软件\\jpskb.exe"), GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
CContainerClass<HANDLE> hContainerClassFile(hFileFile); SOCKET sock = INVALID_SOCKET;
CContainerClass<SOCKET> sContainerClasssock(sock); int i = ;
//CContainerClass<int> iCContainerClassi(i); //int为不识别类型,编译不过
return ;
}

本来想过需不需要把不识别的类型做成一个空的clear函数,就是遇到不认识的类型什么都不做直接跳过。但是后来想想要是这样如果遇到没有对应的资源销毁类恐怕会有内存泄漏,于是让程序遇到不认识的类型直接编译不过即可。

其实写这篇文章有点多此一举,因为实际开发中根本不需要这么做。但是萃取技术作为C++当中一个比较难懂的知识点,如果能设计一个实际用途方案对深入理解还是很有帮助的,所以我感觉并非画蛇添足了。

最新文章

  1. QStandardItemModel-Delegate
  2. IE8 jq focus BUG
  3. msvc2013编译qt5.6源码
  4. 【温故而知新-Javascript】使用Web存储
  5. Linq join
  6. C#基本语句
  7. Spring Framework 中启动 Redis 事务操作
  8. linux ubuntu 浏览器 字 字体 虚 解决办法
  9. 鸟哥的私房菜上 xpenguins 设备(ubuntu 12.04)
  10. 杭电OJ——1011 Starship Troopers(dfs + 树形dp)
  11. Openjudge-计算概论(A)-比饭量
  12. c oth
  13. Java并发编程——BlockingQueue
  14. c++——智能指针学习(shared_ptr和weak_ptr)
  15. 大数据之hiveSQL
  16. Java 中数据库连接池的比较
  17. gdb远程debug A syntax error in expression, near `variable)&#39;.
  18. Dynamic Signals and Slots
  19. Java封装概述
  20. idea快捷键 好的网址收藏

热门文章

  1. (干货)java中如何根据一个时间获取属于本年那一周,本周的开始时间以及最后一天时间。并且设置起始时间为周6.结束时间为周5
  2. python list基本操作一
  3. this.$router.go()和this.$router.push()的差别
  4. sql实现取汉字大写首字母
  5. POJ 2763 /// 基于边权的树链剖分
  6. CSS 命名规范将省下调试时间
  7. 使用SpringBoot1.4.0的一个坑
  8. Pod 私有仓库构建
  9. iOS开发系列-iOS适配
  10. Impala系统架构