天天看点

template

函数模板

以下以取最大值的函数模板maximum为例。此函数在编译时会自动产生对应输入变量的数据类型的实际代码。

#include <iostream>
 
template <typename T>
inline const T& maximum(const T& x,const T& y)
{
   if(y > x)
      return y;
   else
      return x;
}
 
int main(void)
{
   using namespace std;
   //Calling template function
   std::cout << maximum<int>(3,7) << std::endl;         //输出 7
   std::cout << maximum(3, 7) << std::endl;             //和上面相同
   std::cout << maximum<double>(3.0,7.0) << std::endl;  //输出 7
   return 0;
}      

类别模板

以下以将组件指针的操作,封装成类别模板ComPtr为例。

#pragma once
 
template <typename Ty>
class ComPtr
{
protected:
    Ty* m_ptr;
 
public:
 
    ComPtr()
    {
        m_ptr = NULL;
    }
 
    ComPtr(const ComPtr& rhs)
    {
        m_ptr = NULL;
        SetComPtr(rhs.m_ptr);
    }
 
    ComPtr(Ty* p)
    {
        m_ptr = NULL;
        SetComPtr(p);
    }
 
    ~ComPtr()
    {
        Release();
    }
 
    const ComPtr& operator=(const ComPtr& rhs)
    {
        SetComPtr(rhs.m_ptr);
        return *this;
    }
 
    Ty* operator=(Ty* p)
    {
        SetComPtr(p);
        return p;
    }
 
    operator Ty* ()
    {
        return m_ptr;
    }
 
    Ty* operator->()
    {
        return m_ptr;
    }
 
    operator Ty** ()
    {
        Release();
        return &m_ptr;
    }
 
    operator void** ()
    {
        Release();
        return (void**)&m_ptr;
    }
 
    bool IsEmpty()
    {
        return (m_ptr == NULL);
    }
 
    void SetComPtr(Ty* p)
    {
        Release();
 
        m_ptr = p;
        if (m_ptr)
        {
            m_ptr->AddRef();
        }
    }
 
    void Release()
    {
        if (m_ptr)
        {
            m_ptr->Release();
            m_ptr = NULL;
        }
    }
};      
  • ​​Borland​​模型(包含模板编译模式):​​编译器​​​生成每个​​编译单元​​​中遇到的所有的模板实例,并存放在相应的​​目标文件​​​中;​​链接器​​​合并相同的模板实例,生成​​可执行文件​​​。为了在每次模板实例化时模板的定义都是可见的,模板的声明与定义放在同一个.h文件中。这种方法的优点是​​链接器​​​只需要处理​​目标文件​​​;这种方法的缺点是由于模板实例被重复编译,编译时间被加长了,而且不能使用系统的​​链接器​​​,需重新设计​​链接器​​。
  • ​​Cfront/查询​​模型(分离(Separation)模板编译模式):​​AT&T公司​​​的​​C++​​​​编译器​​​​Cfront​​为解决模板实例化问题,增加了一个模板仓库,用以存放模板实例的代码并可被自动维护。当生成一个​​目标文件​​​时,​​编译器​​​把遇到的模板定义与当前可生成的模板实例存放到模板仓库中。​​链接​​​时,​​链接器​​​的包装程序(wrapper)首先调用​​编译器​​​生成所有需要的且不在模板仓库中的模板实例。这种方法的优点是​​编译​​​速度得到了优化,而且可以直接使用系统的​​链接器​​​;这种方法的缺点是复杂度大大增加,更容易出错。使用这种模型的源程序通常把模板声明与非内联的模板成员分别放在.h文件与模板定义文件中,后者单独​​编译​​。
  • 混合(迭代)模型:​​g++​​​目前是基于​​Borland​​​模型完成模板实例化。​​g++​​​未来将实现混合模型的模板实例化,即​​编译器​​​把​​编译单元​​​中的模板定义与遇到的当前可实现的模板实例存放在相应的​​目标文件​​​中;​​链接器​​​的包装程序(wrapper)调用​​编译器​​​生成所需的目前还没有实例化的模板实例;​​链接器​​​合并所有相同的模板实例。使用这种模型的源程序通常把模板声明与非内联的模板成员分别放在.h文件与模板定义文件中,后者单独​​编译​​。

继续阅读