[c++ primer plus]c++ 函数模版,类模版,实例化,具体化,模版作参数,模版的友元

模版不是类或函数,它们是c++编译器指令,它只是一个用于生成类或函数的方案,说明如何生成类或函数。 具体生成时,称为实例化(instantiation)或具体化(specialization)。因此,模版不能单独编译,必须与特定的实例化请求一起使用。最简单的办法就是将所有模版信息放入一个头文件里,使用时include这个头文件。如果编译器支持export关键词,则可以将“类模版”的声明与定义分开存放在.h和.cpp中。

1. 函数模版的重载(利用可以重载的特征标)

template  < class  Any >
void  Swap(Any &  a, Any &  b);

// override
template  < class  Any >
void  Swap(Any *  a, Any *  b,  int  n);

template 
< class  Any >
void  Swap(Any &  a, Any &  b)
{
    Any temp; temp 
= a; a = b; b = temp;
}


template 
< class  Any >
void  Swap(Any *  a, Any *  b,  int  n)
{
    Any temp;
    
for (int i = 0; i < n; i++)
    
{ temp = a[i]; a[i] = b[i]; b[i] = temp; }
}
main( )
{
    int i, j;
    double k[10], m[10];
    Swap(i, j);         //显示实例化为Swap<int>(int&, int&);
    Swap(k, m, 10);    //显示实例化为Swap<double>(double*, double*, int);
}

 2. 函数模版的显式实例化,即可以命令编译器直接创建 template<class Any> 的实例,把 class Any 实例化。

// explicit instantiation
template  void  Swap < int > ( int & int &);
template  void  Swap < Cjob > (Cjob & , Cjob & );

3. 函数模版的显式具体化,它不使用模版来生成函数定义,而应使用独立的、专门的函数定义。显式具体化要有自己的函数定义,而显式实例化则不需要,这是两者本质的区别。两者的相同之处是:都生成了一个具体的函数,而不再是模板。

//  explicit specialization,这两种格式显式实例化的格式等价,只需要一种就可以。
template  <>   void  Swap < Cjob > (Cjob &  a, Cjob & b);
template  <>   void  Swap(Cjob & a, Cjob & b);

template  <>   void  Swap < Cjob > (Cjob &  a, Cjob &  b)
{
    
string tStr;
    tStr   
= a.name;
    a.name 
= b.name;
    b.name 
= tStr;
}


template 
<>   void  Swap(Cjob &  a, Cjob &  b)
{
    
string tStr;
    tStr   
= a.name;
    a.name 
= b.name;
    b.name 
= tStr;
}

4. 函数模版的部分具体化,部分具体化与显式具体化的区别在于:前者还是一个函数模板,而后者则已经是一个函数。前者的函数定义中,必然还有typename类型待定,这个类型将在函数模板被调用的时候得到“隐式”的具体化。

template  < class  T1,  class  T2,  class  T3 >
void  Swap(T1 &  a, T2 &  b, T3 &  c);

// explicit specialization
template  < class  T1,  class  T2 >   void  Swap < T1, T2,  int > (T1 &  a, T2 &  b,  int &  c);

// 部分具体化,可以引入各种限制
template  < class  T1,  class  T2 >   void  Swap < T1,T2, T2 > (T1 &  a, T2 &  b, T2 &  c);
tempate 
< class  T1 >   void  Swap < T1, T1 * , T1 *> (T1 &  a, T1 *   & b, T1 *   & c);

template 
< class  T1,  class  T2,  class  T3 >
void  Swap(T1 &  a, T2 &  b, T3 &  c)
{
..............
}


template 
< class  T1,  class  T2 >   void  Swap < T1, T2,  int > (T1 &  a, T2 & b,  int &  c)
{
..............
}

template <class T1, class T2> void Swap<T1,T2, T2>(T1& a, T2& b, T2& c);
{
.............
}

template 
< class  T1 >   void  Swap < T1, T1 * , T1 *> (T1  & a, T1 *   & b, T1 *   & c)
{
..............
}

5. 类模版之内与之外:在之内声明时可以忽略类型,之外必须Stack<Type>带上类型。

template  < class  Type >
class  Stack
{
public:
    Stack
& operator= (const Stack& st);
}


template 
< class  Type >
Stack
< Type >   &  Stack < Type >  ::  operator = ( const  Stack < Type >&  st)
{
}
main ( )
{
    Stack<string> st;    //隐式的实例化
}

6. 类模版的默认类型参数,不能为函数模版提供默认的类型参数。

template  < class  T1,  class  T2  =   int >  
class  Topo 
{
........
}
;
Topo<double, double> m1;
Topo<double> m2;    //使用默认类型

7a. 类模板的显式实例化

template  < typename T >
class  SortedArray
{
public:
    T val
}
;

template 
class  SortedArray < int > ;

main ( )
{
    SortedArray
<int> sa;  //模板类与模板函数的区别在于:前者被调用时,总是要带有<parameter-type>,而后者则不带。因为后者可以从形式参数来实例化或具体化模板;而前者则只能靠这个后缀,由编译器决定生成哪种类型。(即使已经显式实例化了,也要带上后缀。)
}

7b. 类模板的显式具体化

template  < class  T >
class  SortedArray
{
 ........
}
;

// 显式具体化,定义新的类功能。
template  <>   class  SortedArray < specialized - type - name >  
{
 ........
}
;
main ( )
{
    SortedArray<specialized-type-name> sa;
}

7c. 类模版的部分具体化

template  < class  T1,  class  T2,  class  T3 >
class  SortedArray
{
public:
    SortedArray() 
    
{
        printf(
"1 ");
    }


    T1 val1;
    T2 val2;
    T3 val3;
}
;

template 
< class  T1,  class  T2 >  
class  SortedArray < T1, T2, T2 >
{
public:
    SortedArray()
    
{
        printf(
"2 ");
    }


    T1 val1;
    T2 val2;
}
;

template 
< class  T1 >  
class  SortedArray < T1, T1, T1 >
{
public:
    SortedArray()
    
{
        printf(
"3 ");
    }


    T1 val;
}
;

template 
<>  
class  SortedArray < int int int >
{
public:
    SortedArray()
    
{
        printf(
"4 ");
    }

}
;

int  main( int  argc,  char *  argv[])
{
    SortedArray
<intintint> sa1;
    SortedArray
<intint> sa2;
    SortedArray
<int> sa3;
    
//SortedArray sa4;

    printf(
"Hello World! ");
    
return 0;
}

8. 模版作为模版类的成员

template  < typename T >
class  beta
{
private:
    template 
<typename V>
    
class hold;
    hold
<T> q;
    hold
<int> n;
public:
    template
<typename U>
    U blab(U u, T t);
}
;

// member define
template  < typename T >
template 
< typename V >
class  beta < T > ::hold
{
private:
    V val;
public:
    V Value() 
const {return val;}
}
;

template 
< typename T >
template 
< typename U >
U beta
< T > ::blab(U u, T t)
{
    ........
}
;

9. 模版作为模版的参数,vc++不支持这种使用,g++支持。

template  < typename V >
class  Stack
{
....
}
;

template 
< template  < typename T >   class  Thing >
class  Crab
{
....
}
;

main()
{
    Crab
<Stack> vStack;
}

10. 模版类的非模版友元函数

template  < typename T >
class  HasFriend
{
    
public:
        HasFriend(
const T& i) : item(i) { ct++; }
        
~HasFriend() { ct--; }
        friend 
void counts();
        friend 
void report(HasFriend<T> &);
    
private:
        T item;
        
static int ct;
}
;

void  counts()
{
// 每个类有独立的static变量,模版没有static变量,因为模版只是提供给编译器的方案,本身并不是类。只有模版实例化或具体化之后,才可以访问其static变量。
    cout << "HasFriend<int>: " << HasFriend<int>::ct;  
    cout 
<< "HasFriend<double>:" << HasFriend<double>::ct; 
}


//  必须为每个类提供相应的友元。
void  report(HasFriend < int >   &  hf)
{
    cout 
<< hf.itme;
}


void  report(HasFriend < double >   &  hf)
{
    cout 
<< hf.item;
}


main()
{
    HasFriend
<int> hf1;
    counts();
    HasFriend
<double> hf2;
    counts();
    report(hf2);    
}

10. 模版类的约束模版友元。

// 首先在类定义前面声明-函数是模版函数
template  < typename T >   void  counts();
template 
< typename T >   void  report(T & );

template 
< typename TT >
class  HasFriendT
{
public:
    HasFriendT(
const TT& i) : item(i) { ct++; }
    
~HasFriendT() { ct--; }
//在类里再次声明为友元,这里也是某种程度上的实例化,
//但还没有彻底实例化,函数还是模版。
    friend void counts<TT> ();
    friend 
void reports<HasFriendT<TT> > (HasFriendT<TT>&);
//这里也可以写做:
//friend void reports<> (HasFriendT<TT>&);
//让编译器自己判断模版的参数类型!
private:
    TT item;
    
static int ct;
}
;

template 
< typename T >
int  HasFriendT < T > ::ct  =   0 ;

template 
< typename T >
void  counts()
{
//这里并不是要输出模版的大小、模版的static成员变量。因为程序运行时,并不存在模版的实体,
//都是实例化后的确确实实存在的类。因此,这里指的实例化的类。
    cout << "template size: " << sizeof(HasFriendT<T><< "";
    cout 
<< "template counts(): " << HasFriendT<T>::ct << endl;
}


template 
< typename T >
void  report(T &  hf)
{
    cout 
<< hf.item << endl;
}


int  main()
{
    counts
<int>(); //隐式实例化counts,由模版函数变为具体的函数

    HasFriendT
<int> hfi1(10); //隐式实例化类,并定义该实例化类的一个对象
    HasFriendT<int> hfi2(20); 
    HasFriendT
<double> hfdb(10.5);

    report(hfi1); 
//通过调用,隐式实例化函数
    report(hfi2);
    report(hfdb);

    
return 1;
}

 11. 模版类的非约束模版友元。

template  < typename T >
class  ManyFriend
{
public:
    ManyFriend(
const T& i) : item(i) {}
    template 
<typename C, typename D> friend void show2(C&, D&);
private:
    T item;
}
;

template 
< typename C, typename D >
void  show2(C &  c, D &  d)
{
    cout 
<< c.item << "" << d.item << endl;
}


int  main()
{
    ManyFriend
<int> hfi1(10);
    ManyFriend
<int> hfi2(20);
    ManyFriend
<double> hfdb(10.5);
    cout 
<< "hfi1, hfi2: ";
    show2(hfi1, hfi2);
    cout 
<< "hfdb, hfi2: ";
    show2(hfdb, hfi2);
    
return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值