c++Templates学习笔记(二)

第五章:技巧性知识

(1)关键字typename,在c++标准化过程中,引入关键字typename是为了说明:模版内部的标示符可以是一个类型

template <typename T>
class MyClass
{
   typename T::SubType* ptr;
}; 
上面的程序中,第二个typename被用来说明,SubType是定义于类T内部的一种类型,因此,ptr是一个指向T::SubType类型的指针。如果不使用typename,SubType就会被认为是一个静态类型,那么它应该是一个具体的变量或者对象,于是,下面表达式T::SubType * ptr会被看做是类T的静态成员SubType和ptr的乘积。

(2)使用this->.

template <typename T>
class Base 
{
   public:
      void exit();
};
template<typename T>
class Derived :Base<T>
{
   public:
    void foo()
    {
       exit();//错误的调用,因为如果父类被特化了,没有了exit()函数了,这个调用将是不正确的调用,为了能够正常的调用,你必须
               //明确的告诉编译器这个函数式存在的,解决办法就是使用this->exit();或者使用Base::exit()
    } 
};
(3)成员模版

类成员也可以是模版。嵌套类和成员函数都可以作为模版。模版的实例之间能够相互赋值必须满足的条件是模版的实例必须是同一种类型,如:

Stack<int> intStack1, intStack2;
Stack<float> floatStack;

intStack2 = intStack1; //正确的赋值
floatStack  = intStack1 ; //错误的赋值
然而可以采用重载赋值运算符达到赋值的目的。

template<typename T>
class Stack
{
private:
    deque<T> elems;
public:
    void push( T const& );
    void pop();
    T top() const;
    bool empty() const;
    //使用元素类型为T2的栈进行赋值
    template<typename T2>
    Stack<T>& operator= ( Stack<T2> const& );
};

template<typename T>
template<typename T2>
Stack<T>& Stack<T>::operator= ( Stack<T2> const& op2 )
{
    if( (void*)this == (void*)&op2 ) //如果是同一份则直接返回
        return *this;

    Stack<T2> tmp( op2 );
    elems.clear();
    while( !tmp.empty() )
    {
        elems.push_front( tmp.top() );
        tmp.pop();
    }
    return *this;
}
这个例子中就是用了成员模版。

(4)模版的模版实参匹配

(5)使用字符串作为函数模版的实参

对于字符串,在实参演绎过程中,当且仅当参数不是引用时,才会出现数组到指针的类型转换,如果是引用,则一直用的是数组,看下例

template <typename T>
inline T const& max ( T const& a, T const& b)
{
    return a> b? b: a;
}
::max( "apple" ,"peach" );//正确,相同类型的实参
::max( "apple" ,"tomato"); //错误,因为长度不一样,又是引用,所以认为是不同类型

template <typename T>
inline T  max ( T  a, T  b)
{
    return a> b? b: a;
}
::max( "apple" ,"peach" );//正确,相同类型的实参
::max( "apple" ,"tomato"); //正确,退化为char*类型
第六章:模版实战

(1)包含模型

为了能够让模版能够正常的编译,可以采用三种方法进行解决:第一种,将定义和实现都写在头文件中,然后包括头文件;第二:将定义和实现分开写在.C和.CPP文件中,然后在.H文件的最后包含,CPP;第三:.C和.CPP都包含在文件中。缺点就是:把声明和实现都放在头文件中,会增加头文件的大小,增加编译时间。

(2)显式实例化

显式实例化的格式:template 返回值类型 函数名<数据类型>(具体函数类型 形参);例如:template void func<double>(double const&);并且要注意显式实例化只能实例一次。优点是不需要采用包含模型增大头文件,缺点是必须跟踪每个需要实例化的实体,对于大项目,将带来巨大的负担。

(3)分离模型

使用关键字export,但现在不常用。


你可能感兴趣的:(c++Templates学习笔记(二))