记录学习过程中的点点滴滴
2012年七月

C++插件机制的一种实现方法(对象工厂)
七 21st
背景
在我们的实际开发过程中,经常会开发一些插件,比较常见的例子如:给你 DataHandler,它是一个抽象类,提供一些数据操作的接口,然后插件开发者就需要继承DataHandler,并按需求实现对应的接口,将其作为插件,编译到最终的二进制程序中,最后通过配置文件指定生效该插件。
// data_handler.h Class DataHandler { public: virtual bool Handle(std::vector<Data*> data_list) =0; virtual ~DataHandler(){} }; REGISTER_REGISTER(DataHandler) #define REGISTER_DATA_HANDLER(name) REGISTER_CLASS(DataHandler, name)
// my_data_handler.h class MyDataHandler : public DataHandler { public: virtual bool Handle(std::vector<Data*> result_list); };
// my_data_handler.cc bool MyDataHandler::Handle(std::vector<Data*> data_list) { // Implemention... } REGISTER_DATA_HANDLER(MyDataHandler)
// configure file DataHandler{ name : MyDataHanlder, prior : 1 } DataHanlder{ name : YourDataHandler, prior : 1 }
此时你只需把你的MyDataHandler编译为动态库或者是静态库,并链接到最终二进制中,在数据处理时就会调用你的DataHandler。是不是很方便开发哈,这就是所谓的插件开发思想。下面主要介绍下具体的实现。
实现思想
想要实现上述功能的插件框架,主要从以下几个方面着手解决:
1. 如何组织不同类型的插件,如目前有DataHanlder,但是系统可能也支持ServiceHanlder等等;某类插件可能包含多个具体的实例的插 件,那又如何组织;这里很容易就想到了双层map的数据结构,如下图所示,每层Map的Key都插件类型或者具体插件名字,value为对应的工厂对象, 工厂对象生成对应的实例,具体如下图所示:
2. 如何生成对象工厂类呢? 这里首先不能将这个工作交给插件开发者,一方面开发量增大,另一方面也暴漏系统实现细节;但是也不能框架开发者手工实现,因为框架本身无法预知都有哪些插件需要开发。
所以可能的方法包括模板函数或者是宏定义了,本文使用宏定义进行实现,包括插件类型工厂和某个插件工厂。
scoped_ptr,shared_ptr和weak_ptr用法和实现方法
七 14th
scoped_ptr, shared_ptr和weak_ptr的都称为智能指针,但是各个的用法都不太一样,
本文就就详细介绍其具体用法以及具体实现方法。
-
用法介绍
- scoped_ptr: “scoped”即作用域的含义,主要用于指针在某个作用域中有效,当离开作用域时,该指针自动释放,这就避免了出现忘记回收内存的情形,同时scoped_ptr的复制构造函数和赋值函数为私有,这样就避免了指针的传递, 示例如下:
- shared_ptr: 共享所有权的智能指针,当某个对象需要在多个地方使用时,被多个指针引用,此时程序可能就无法确定在何时释放该对象,因此就需要使用“引用计数”的方法,当对象被引用的次数为0时,自动释放该对象,示例代码如下:
- weak_ptr: shared_ptr是强引用,而weak_ptr是弱引用;当使用shared_ptr出现循环引用时,造成内存无法释放,如果 你能预料到此种情况发生,你就应该使用weak_ptr类型;另外weak_ptr不会增加所指对象的引用计数,但是会增加计数器的对象引用计数,这点可以后面的实现中看到这点,详细请点击这里
scoped<T> g_ptr; { scoped_ptr<T> ptr(new T); g_ptr = ptr;//illegal, because the assign operator is private. //T* will deleted when it goes out of this scoped. }
shared_ptr<T> g_ptr; { shared_ptr<T> ptr<new T>; // reference count is 1. g_ptr = ptr; //now reference count is 2 // when it goes out of this scoped, the reference count is 1 } //the reference count is 1. g_ptr->foo();
-
实现原理
- scoped_ptr的实现:其主要是在其析构函数中delete对象,同时将copy constructure 和 assign operator设置为私有,避免了指针的传递,这点比auto_ptr安全的多;另外scoped_array是针对new[]和delete[]的只能指针,具体实现请见附件。
- shared_ptr的实现:其主要用到了引用计数,每个指向同一对象shared_ptr都指向同一个计数器,其中计数器的定义如下,当shared_ptr对象复制时,对象引用计数加1,当shared_ptr对象释放时,引用计数减1,当引用计数减为0时,delete所指的对象。具体实现请看附件。
- weak_ptr的实现:需要注意的一点weak_ptr需要使用shared_ptr构造,不能直接使用原始指针进行构造,它主要操作的是weak_count_计数器,具体实现请看附件。
// This class is an internal implementation detail for shared_ptr. class SharedPtrControlBlock { template <typename T> friend class shared_ptr; template <typename T> friend class weak_ptr; private: SharedPtrControlBlock() : refcount_(1), weak_count_(1) { } int refcount_; //对象的引用计数 int weak_count_; //weak_ptr的引用计数 };
近期评论