美文网首页
Effective c++ 学习笔记(item41)

Effective c++ 学习笔记(item41)

作者: 懒生活 | 来源:发表于2022-09-15 16:53 被阅读0次

    # 理解模板编程的隐式接口和编译器多态

    面向对象的编程思路以显示的接口和运行期的多态为主要提现。编写一个类数据被封装成private。 对外呈现的函数接口即是显式接口,函数有可能是virtual的。所以在运行期会有一次根据对象动态类型进行调用的多态过程。

    面向模板的泛型编程思路和面向对象不一样。它考虑的是使用模板的这个区块,对对象的隐式接口要求。只要对象满足隐式接口的要求,就可以使用这个区块代码。而这个区块代码有可能是个通用的流程。

    # 理解模板的使用方法

    模板的使用大致有3种场景,一种是函数模板,一种是类模板,还有模板特化

    ## 函数模板

    函数模板的定义形式如下

    ```

    template<typename C>

    void printObjName(C obj)

    {

        std::cout<<obj.getName()<<endl;

    }

    ```

    函数模板往往要实现的是一段通用代码,可以给多个类型对象使用。只要这个类型对象满足函数模板的隐式接口要求就可以。函数模板是通过入参具现化的。所以定义的函数模板参数,一定是这个函数的入参之一。

    在实际使用过程中, 编译器通过入参的对应关系来具现化函数模板。

    ## 类模板

    函数模板比较好理解。可以理解为一个通用的代码功能段。那么类模板如何理解呢。vector就是一个类模板。他的目的是在连续空间中维护数据,至于数据是啥类型,他不管。所以在编程的时候希望无论什么样的数据都能维护到类里面。这就需要借助模板类。

    ```

    template<typename C>

    class DataMgr

    {

        private:

            C data[1000];

    ....

    }

    ```

    类似上述的DataMgr类。他的目的是把通用的管理接口在类模板上只要实现一份。这些接口不关心数据的类型。当这个模板类实际使用具现化的时候,会根据实际类型,具现化不同内存在用的类出来。

    模板类需要显示的指定实参,否则编译器没有办法想模板函数那样自动推导出来。

    所以上述的模板类在具现化的时候要用类似如下的代码`DataMgr<int> oneIntDataMgr;`

    ## 模板特化

    模板特化是给模板类,模板函数预留的后门。可以理解是用来弥补设计缺陷的。比如你设计了个通用的程序段,本以为这个程序段对所有满足条件的对象都适用。但是最终你发现就是有那么一种对象,需要特殊处理一下下。这时候就需要用到模板特化

    ```

    template<typename C>

    void printObjName(C obj)

    {

        std::cout<<obj.getName()<<endl;

    }

    template<>

    void printObjName<SpecialObj>(SpecialObj obj)

    {

        std::cout<<obj.Name()<<endl;

    }

    ```

    我的问题是与其这样写一个别扭的特化,为什么不直接来一个重载函数`void printObjName(SpecialObj obj)` 如果特化和重载函数同时存在,编译器是什么表现?

    这里用vs2019的编译器简单做个实验

    ```

    template<typename C>

    void printName(const C&obj){cout<<obj<<endl;}

    template<>

    void printName<int>(const int&obj){cout<<"这是特化版本调用"<<endl;}

    void printName(const int&obj){cout<<"这是普通重载函数"<<endl;}

    int main()

    {

        string obj="stringobj";

      printName(obj);

      printName(15);

    }

    ```

    从上面的实验可以发现当这三个printName同时存在的时候编译器不会报错。编译器优先选择重载函数,其次是选择特化函数,如果这两个都没有,才会用普通的模板参数。

    要注意的是普通函数和特化模板函数不广在优先级上有差异。 还有一个差异是,编译器在尝试普通函数的时候会允许隐式转换。但对特化模板函数,是不允许隐式转换的。

    相关文章

      网友评论

          本文标题:Effective c++ 学习笔记(item41)

          本文链接:https://www.haomeiwen.com/subject/rdbhortx.html