Effectiv C++ (07)

来源:互联网 发布:珠海设计院使用软件 编辑:程序博客网 时间:2024/06/11 05:24

条款41:了解隐式接口和编译器多态

Template<typename T>

Void doProcessing (T& t)

{

If (w.size() > 10 && w != someNastyWidget)

{

    T temp(w);

    Temp.normalize();

    Temp.swap(w);

}

}

必须支持:size、normalize、swap、拷贝构造、不等判断

这一组表达式是T必须支持的一组隐式接口

凡设计w的任何函数调用,operator> operator!=,可能造成template具现化,是调用成功。这些具现化发生在编译时期。“以不同的template参数具现化function template”,会导致调用不同的函数。这是所谓的编译器多态。

运行期多态、编译期多态差异:virtual(运行期)、template(编译期),差异明显

显示接口、隐式接口:

显示接口由函数的签名(返回值、名称、参数、常量性)构成。

隐式接口不基于签名式,而是有效表达式

Template<typename T>

Void doProcessing (T& t)

{If (w.size() > 10 && w !=someNastyWidget)…}

它必须提供一个名为size的成员函数,该函数返回int类型

它必须提供一个支持operator!=函数,用来比较两个对象

函数可能从父类中继承而来。

 

对于class和template:

         都支持多态和接口

         class的接口是显式的,以函数签名为中心,多态则是virtual函数发生于运行期

         template的接口是隐式的,基于有效表达式,多态是在编译期通过template具现化和函数重载解析实现

条款42:了解typename的双重定义

template<typename T>

template<classs T>

两者没有区别。

vector<int> vec;

vector<int>::const_iterator itr = vec.begin();

可以访问vec中的元素,但不能修改

const int * conPtr;

说明某个name是个类型,要在其前面加typename

typenameC::const_iterator itr;

Template<typename C>

Void f(const C& container, typename C::iterator iter);

typename必须作为嵌套从属类型名称的前缀词

         例外:typename不可以出现在baseclasses list内的嵌套从属类型名称之前,也不可以出现在成员初始化列表中作为base class的修饰符

Template <typename T>

Class Derived:public Base<T>::Nested    // 不能出现在继承列表中

{

Public:

Explicit Derived(int x):

Base<T>::Nested(x)              // 不能出现在初始化列表中

{

    Typename Base<T>::Nested temp; // 其他位置需要

}

};

Template<typename IterT>

Void workWithIterator(IterT iter)

{

    Typename std::iterator_traits<IterT>::value_type temp(*iter); //类型IterT对象所指之物的类型

}

Template<typename IterT>

Void workWithIterator(IterT iter)

{

Typedef typename std::iterator_traits<IterT>::value_type value_type;

Value_type temp(*iter);

}

emplate内出现的名称如果相依于某个template参数,称之为从属名称(dependent names),如果从属名称在class内呈嵌套关,则称之为嵌套从属名称(nested dependent name)。如果解析器在template中遭遇一个嵌套从属名称,它便假设这名称不是个类型,除非你明确告诉它是,做法是在它之前放置关键字typename。typename只能被用来验明嵌套从属类型名称,其他名称不该有它存在。同时,typename不可以出现在baseclass list内的鞋套从属类型名称之前,也不可在member initialization list中作为baseclass修饰符

template<typename C>

void print2nd( const C& container ){

  if( container.size() >= 2 ){

    //C::const_iterator即为一个嵌套从属名称,

    //编译器默认假设它不是个类型

    //因此这段代码不合法

    C::const_iterator iter(container.begin());

    ++iter;

    int value = *iter;

    std::cout<<value;

  }

}

//修改一下:

template<typename C>

void print2nd( const C& container ){

  if( container.size() >= 2 ){

    //在C::const_iterator前放置关键字typename

    //明确说明该嵌套从属名称是一种类型。

    typename C::const_iterator iter(container.begin());

    ...

  }

}

//typename不能出现在base class list或member initialization list中

template<typename T>

class Derived: public Base<T>::Nested{

  public:

    explicit Derived( int x ):

      Base<T>::Nested(x){

         typename Base<T>:Nested temp;

         ...

      }

};

//如果编译器不知道Base<T>::nested是什么,可以在前面先用typedef

typedef typename Base<T>::Nested Nested;

 

//然后凡需要Base<T>::Nested的地方则使用Nested。

条款43:学习处理模版化基类内的名称

条款44:将与参数无关的代码抽离template

抽离共同部分,形成新函数

条款45:运用成员函数模版接收所有兼容类型

成员函数模版

Template <typename T>

Class SmartPtr

{

Public:

Template<typename U>

SmartPtr(const SmartPtr<U> &other); // 对于任何的T、U,可以根据S<U>生成S<T>

};