很久没有用心的读过一本书了,今天静下心来,认真的看了过去一直在看的云风的书(游戏之旅-我的编程感悟)。这本书从两个月前都开始看,吊吊当当的持续到现在,很多章节浅尝辄止。说实话,有些章节是真心看不懂。看看大牛们的书,自己真是羞愧难当。没办法,既然难以望其项背,自己唯而加快奔跑。今天仔细阅读了C++的一章,受益不少,谨以此记录以备忘。
template的使用技巧
1,封装c++的成员函数调用
这个类需要在调用成员函数的之前和之后自动调用call和return函数。例如欲记录函数的调用历史,作一些前期分配和后期清理的工作。
class monitor { void call() {} void return() {} }
如何实现这种技巧? 仔细思考应该是借用析构函数的特性,
template <typename T> class WrapFunction { private: WrapFunction(); WrapFunction(const WrapFunction&); WrapFunction& operator=(const WrapFunction&); T* m_pT; private: class CallHelper { private: T* m_pT; CallHelper(T* p): m_pT(p){} public: ~CallHelper(){ m_pT->after(); } T* operator->()const { return m_pT; } friend class WrapFunction<T>; }; public: WrapFunction(T& obj): m_pT(&obj){} CallHelper operator->() const { m_pT->before(); return CallHelper(m_pT); } };
如何使用它:
Test obj; WrapFunction<Test> t(obj); t->print();
主要有几个技术点:
1,如何调用before函数?可以通过WrapFunction重载->运算符
2,为什么要使用CallHelper这个类呢? 由于需要在调用print结束之后调用after。
3,使用了局部对象析构的策略,在析构中调用after。
4,使用了友元类的方案来使得CallHelper的构造函数私有化,以避免外部可能使用此CallHelper类。
5,CallHelper类中也使用了m_pT指针,以使得外面的m_pT可以定义为私有,避免外部使用。
有几个技术都是为了使外部类WrapFunction的方法尽量私有化,仅仅公开两个方法。一个构造函数,一个重载。默认构造和copy,赋值通通禁止调用。
2,对象计数
项目中出现内存不断扩张,重载operator new也没有发现未释放的对象。只好通过给项目中的每一个类增加一个对象计数器来跟踪对象的创建情况。
通过添加max变量来跟踪对象创建的最大个数。
class counter_data { public: counter_data(const char* name) :_name(name){ printf("name:%s this:%p\n", name, this); } ~counter_data(){ printf("name:%s this:%p count:%d\n", _name, this, current_count()); } void inc() { if(++_counter > _max){ _max = _counter; } } void dec() { --_counter; assert(_counter >= 0); } int current_count() const{ return _counter; } int max_count() const{ return _max; } private: int _max; int _counter; const char* _name; }; template <typename T> class counter { public: counter() {_data.inc();} counter(const counter& rhs){ _data.inc(); } ~counter(){ _data.dec(); } public: int current_count()const { return _data.current_count(); } int max_count() const{ return _data.max_count(); } private: static counter_data _data; }; template<typename T> counter_data counter<T>::_data(typeid(T).name());
如何使用它?只需要添加一个私有实例变量即可。
class Object { public: ~Object(){ printf("Object count:%d\n", _couter.current_count()); } private: counter<Object> _couter; };
counter是一个模板类,它持有一个静态数据成员_data。由于此模板类的模板参数类型是T, 也就是各种要被计数的对象类型,那也就是说会有多个counter类的实现,也就是会有多个_data对象。counter_data在创建的时候会注册name和自身指针,可以通过在counter_data类中添加更详细的log来详细跟踪Object对象的创建过程。