代理设计模式也可以使用模板实现,智能指针就是一个例子。下面就是一个没有使用模板的简单版本智能指针。
程序46.
#include <iostream> using namespace std;
class Inner { public: void Fun() { cout << "Inner::Fun" << endl; } };
class Outer { private: Inner* m_pInner;
public: Outer(Inner* p_pInner) : m_pInner(p_pInner) { }
Inner* operator -> () { return m_pInner; } };
int main() { Inner objInner; Outer objOuter(&objInner);
objOuter->Fun();
return 0; } |
程序的输出为:Inner::Fun()
简单地说来,我们仅仅重载了->运算符,但是在实际的智能指针中,所有必须的运算符(例如=、==、!、&、*)都需要被重载。以上的智能指针有一个大问题:它只能包含指向Inner对象的指针。我们可以编写Outer类模板来取消这一限制,现在让我们来略微修改一下程序。
程序47.
#include <iostream> using namespace std;
class Inner { public: void Fun() { cout << "Inner::Fun" << endl; } };
template <typename T> class Outer { private: T* m_pInner;
public: Outer(T* p_pInner) : m_pInner(p_pInner) { }
T* operator -> () { return m_pInner; } };
int main() { Inner objInner; Outer<Inner> objOuter(&objInner);
objOuter->Fun();
return 0; } |
程序的输出和前一个一样,但是现在Outer类就可以包含任何类型了,只需要把类型作为模板参数传递进来即可。
ATL中有两个智能指针,CComPtr和CComQIPtr。
你可以用模板做一些有趣的事情,例如你的类可以在不同的情况下成为不同基类的子类。
程序48.
#include <iostream> using namespace std;
class Base1 { public: Base1() { cout << "Base1::Base1" << endl; } };
class Base2 { public: Base2() { cout << "Base2::Base2" << endl; } };
template <typename T> class Drive : public T { public: Drive() { cout << "Drive::Drive" << endl; } };
int main() {
Drive<Base1> obj1; Drive<Base2> obj2; return 0; } |
程序的输出为:
Base1::Base1 Drive::Drive Base2::Base2 Drive::Drive |
在这里,Drive类是继承自Base1还是Base2是由在对象创建的时候传递给模板的参数决定的。
ATL也使用了这一技术。当你使用ATL创建COM组件的时候,CComObject就会继承自你的类。在这里ATL利用了模板,因为它不会预先知道你用来作COM组件而创建的类的名称。CComObject类定义于ATLCOM.H文件之中。
在模板的帮助下,我们也可以模拟虚函数。现在让我们重新回忆一下虚函数,下面是一个简单的例子。
程序49.
#include <iostream> using namespace std;
class Base { public: virtual void fun() { cout << "Base::fun" << endl; }
void doSomething() { fun(); } };
class Drive : public Base { public: void fun() { cout << "Drive::fun" << endl; } };
int main() { Drive obj; obj.doSomething();
return 0; } |
程序的输出为:Drive::fun
|