构造函数,析构函数不为public时
当constructor, destructor为protected时, 不允许实例化这个类,不管是在栈中还是在堆中, (但可以实例化派生类(protected 的 constructor可以在派生类中调用)) , 当在栈中实例化一个类时, 需要constructor和destructor都是public的, 而在堆中new时 ,需要constructor是public的, 而当调了delete时, 才需要destructor是public的 , 当constructor为private时, 不仅不允许实例化这个类, 也实例化不了派生类(private constructor只能在本类成员中调用), 而这种情况常用来实现 单例 设计模式
单例设计模式(Singleton) , 在我们的talk中用到了 boost::pool::detail::Singleton_default 这个模板类来实现单例 , 但这是用于boost内部的, 在最新的版本中我就没有看到这个类了(这个有点像我研究enable_shared_from_this时的情况), 所以我们可以最好直接写单例类, 像直接把 boost的实现用过来也行, boost/pool/detail/singleton.hpp 这个文件没有包含任何其它头文件, 以下是boost::pool某个版本的实现
1 template<class T> 2 class Singleton { 3 private : 4 struct object_creator { 5 object_creator() { Singleton<T>::instance(); } 6 inline void do_nothing() const{ } 7 } 8 static object_creator create_object; 9 Singleton(); 10 public : 11 typedef T ObjectType; 12 static ObjectType& instance () { 13 static ObjectType obj; 14 create_object.do_nothing(); 15 return obj; 16 } 17 } 18 template<class T> 19 typename Singleton<T>::object_creator 20 Singleton<T>::create_object;
我们的talk中定义了大概是这样一个 macro #define MY_INSTANCE(className) Singleton<className>::instance(); 在每个单例类使用的地方, 如TalkServer, MY_INSTANCE(TalkServer)就会返回 TalkServer 的唯一引用
以上实现的Singleton是一个类模板, 类模板在程序中任何一个地方被引用的时候, 都会根据模板参数去生成一个类(编译过程中), 根据上面的实现, 应该是相应的 static 成员变量的定义也会加上, 然后static member 的初始化会在 main函数执行之前, 也是就main函数执行之前 我们要使用的单例类已经有了, 被Singleton<T>生成的类所持有着, 以局部静态变量的形式(不是成员), (member function和global function中的static 变量应该是一样的吧)
在effective中有一条 make sure base classes have virtual destructor , 一个类若有可能作基类, 其 destructor一定要是 virtual的 在类内部要调用析构(会有这个必要吗) 时, delete this
boost::utility 中 noncopyable 的实现, 在boost namespace 下
1 class noncopyable{ 2 protected : 3 noncopyable () {} 4 ~noncoyable () {} 5 private : 6 noncopyable (const noncopyable&); 7 const noncopyable& operator= (const noncopyable&); 8 }
constructor, destructor为protected,派生类可以实例化, 从noncopyable派生, 则不可被赋值, 不可拷贝 copy constructor和重载的operator= 是不可以被派生类所继承的,好像这是除constructor,destructor外唯一不可被继承的member function
注意后两个函数只被声明了, 没有实现, 这样是可以的, 只有在链接的时候若用到了这个函数,才会去寻找它的定义,生成.o是不会报错的,而如果从noncopyable派生,使用了operator=,在生成.o即编译的时候就会报错了