条款22:果断放弃二进制重用,而采用模版编写智能指针
更多条款请前往原文出处:http://blog.youkuaiyun.com/liuchang5
你看到了很多智能指针是用模版编写的,它们能让智能指针应用于更多的类型之上。这个可以理解。但是所有接口从IUnknown“单源继承”的概念会让你有放弃模版这种复杂技术的念头。你或许会想,如果那样的话,我们就能塑造出一个二进制级别可重用的智能指针,而且没有模版的参与,可以减少编写过程中一些复杂的特化过程。看看下面这个智能指针是否适用:
class MyComSmartPtr
{
public:
MyComSmartPtr(IUnknown *pI) : m_pI(pI){};
~MyComSmartPtr()
{
if (m_pI)
m_pI->Release();
};
private:
IUnknown *m_pI;
};
他已经是个稍微合格的资源管理对象了。而且没有讨厌的模版,确实减少了复杂度,也使得代码在二进制层面上能得以复用(你可能把他编译成DLL,而模版却必须将源码放在头文件中)。
额~ 让我们回顾一下条款7,智能指针除了完成资源管理的功能之外还得像个指针。那么让我们先给他加上一个->操作符。
IUnknown* operator->() const throw()
{
ATLASSERT(p!=NULL);
return IUnknwon* m_pI;
}
让->来返回一个IUnknown的指针确实让人觉得有点不自在,因为你可能会需要一个向下转型来实现某些功能。
func(IMyinteface *pInterface)
{
MyComSmartPtr<IMyInterface*> spMyInterface(pInterface);
dynamic_cast<IMyInterface*>(spMyInterface)->DoSomething(); //语法纠结且不安全
}
哦~ 上面这个纠结的用法,可能足以让你放弃掉依赖从IUnknown的“单源继承”特性来实现一套在二进制级可重用的智能指针的想法。RTTI的开销、类型安全性以及运行时可能产生的错误都是不容乐观的。同时模版相对于使用时的向下转型或许要简单和安全得多。知道如上这些,我想你不会再拒绝模版了~