由于今天还是继续在做万恶的(Android的)recovery升级,而每次编译都要半个多小时,然后就抽空又来写了一点点代码。
在进入正题之前,先对之前的代码做一点小小的改动:
1. PointerDeleter
类不再是模板而直接使用外围类SharedPtr
的模板参数
2. SharedPtr
的模板参数从Reference
改为Resource
由于比较简单,这个小改动就不上代码了。
首先来说说转型(cast)。我们希望SharedPtr
能够支持下面这样的操作:
class Base {};
class Derived : public Base {};
SharedPtr<Base *> sp{
new Derived{}};
就之前的实现而已,毫无疑问,这个操作是不允许的。因为模板参数是Base *
,而函数参数的类型是Derived *
。
我们这里希望的是,他能够像普通的指针一样,比较,子类指针可以安全地赋值给父类指针。同时,对于这对于我们实现运行时多态(runtime polymorphism)也至关重要。
那么,我们又当如何实现呢?
首先我们应该明确的一点是,对于用户实际使用的任一参数化类型,我们都没有办法知道他到底有多少个子类,多什么样的子类!于是,为了达到上面的目标,我们的构造函数需要能够接受类型不确定完全参数。
讲到这里,答案其实已经很明确了,能够接受任意类型作为参数的,只能是函数模板了。
template<typename T>
SharedPtr(T t);
好吧,我说谎了,我们需要的不是任意类型,而是任意能够进行安全转换的类型。那么,现在的问题就是,我们该如何得知,参数的实际类型是符合要求的呢?答案是,我不知道。事实上,作为一个库函数作者,我们也没有办法进行验证。但是,事情也并非没有任何转机。虽然我们没法验证,但是编译器可以帮我们验证。
继续上面的实例:
SharedPtr<Base *> sp{ptr};
这里我们先不管如何验证ptr
指针