zoukankan      html  css  js  c++  java
  • 高效C++:模板和泛型编程

      模板和泛型编程的关注重点在编译期,所有的行为都在编译期确定,因此其规则和玩法也有自己特殊的一套,和其他模块不通用。

     

    了解隐式接口和编译期多态

    • 元编程------编译器多态,决定哪个重载函数被调用

    • class的特点:

      • 显示接口

      • 运行期多态

    • template的特点:

      • 隐式接口

      • 编译器多态,模板的具现和函数的重载

    了解typename的双重含义

    • 声明template参数时,前缀关键字class和typename可以互换

    • 使用typename关键字声明嵌套从属类型名称,但不可以出现在基类列表和初始化里列表中

    • 嵌套从属名称

    template<typename C>
    void Print2Nd(const C& container)
    {
        ...
       typename C::const_iterator iter(container.begin()) //确认是类型不是名称
        ...    
    }
    
    //C::const_iterato 从属嵌套类型(名称中依赖于template类型参数)

    学习处理模板化基类内的名称

    • 在Derived class template中调用base class template的函数时,直接调用编译不过,可以使用如下方法:

      • this->xxx (建议)

      • basename::xxx

      • using basename::xxx

    class CompanyA{
    public:
        CompanyA(){}
    
        void Send()
        {
            cout<<"CompanyA::Send()"<<endl;
        }
    };
    
    class CompanyB{
    public:
        CompanyB(){}
    
        void Send()
        {
            cout<<"CompanyB::Send()"<<endl;
        }
    };
    
    template<typename Company>
    class Sender{
    public:
        Sender(){}
        
        void SendMsg()
        {
            Company c;
            c.Send();
        }
    };
    
    
    template<typename Company>
    class LogSender: public Sender<Company>
    {
    public:
        using Sender<Company>::SendMsg;  
    
        void LogSendMsg()
        {
            cout<<"LogSender::LogSendMsg() before"<<endl;
            
            SendMsg();  //单独使用错误,配合using使用ok
            this->SendMsg(); //OK
            Sender<Company>::SendMsg(); //OK
            
            cout<<"LogSender::LogSendMsg() after"<<endl;
        }
    
    };

    将与参数无关的代码抽取template

    • 不要将函数参数提取为template,这样导致代码冗余

    运用成员函数模板接受所有兼容类型

    • 使用模板成员函数生成可接受和兼容所有类型的函数,包括构造函数

    template<typename U>
    class A
    {
    public:    
        template<typename T>
        A(A<T>& other)
        {
            ...
        }
    };
    • 如果将构造函数声明为模板函数,为了阻止编译器生成默认的构造函数,你必须明确声明一个非模板的构造函数

    需要类型转换时请为模板定义非成员函数

    • template在推倒虑隐式转换

    • 对比“定义no-member函数进行类型转换”这一条规则

    template<typename T>
    const Rational<T> doMutliply(const Rational<T>& lhs, const Rational<T>& rhs)
    {
        ...
    }
    
    template<typename T>
    class Rational
    {
    public:
        ...
        //声明为friend函数的目的是tempalte推倒,保证编译通过,根本目的是提供一个使用是所有类型的乘法   
        frined const Rational<T>operator*(const Rational<T>& lhs, const Rational<T>& rhs)
        {
            return doMutliply(lhs, rhs);
        } 
    }

    请使用traits classes表现类型信息

    • 需要了解STL编程,可以参考《STL源码剖析》一书

    • 运用到模板、元编程等知识

    了解template元编程

    • 元编程将运行期的工程提前到编译期,错误的发现更早,效率更高

  • 相关阅读:
    HLG 1522 子序列的和【队列的应用】
    POJ 3273 Monthly Expense【二分】
    HDU 4004 The Frog's Games 【二分】
    POJ 2001 Shortest Prefixes【第一棵字典树】
    POJ 2823 Sliding Window【单调对列经典题目】
    HDU 1969 Pie 【二分】
    POJ 3125 Printer Queue【暴力模拟】
    POJ 3250 Bad Hair Day【单调栈】
    字典树【模板】
    验证码 Code
  • 原文地址:https://www.cnblogs.com/chusiyong/p/11452786.html
Copyright © 2011-2022 走看看