zoukankan      html  css  js  c++  java
  • STL 萃取(Traits)机制剖析

    模板特化

    在将萃取机制之前,先要说明模板特化

    当有两个模板类,一个是通用泛型模板,一个是特殊类型模板,如果创建一个特殊类型的对象,会优先调用特殊的类型模板类,例如:

    template <typename T>	//泛型模板
    class MyClass
    {
    public:
    	MyClass()
    	{
    		cout << "T MyClass!" << endl;
    	}
    	~MyClass()
    	{
    		cout << "~T MyClass!" << endl;
    	}
    };
    
    template<>
    class MyClass<int>	//全特化模板
    {
    public:
    	MyClass()
    	{
    		cout << "int MyClass!" << endl;
    	}
    	~MyClass()
    	{
    		cout << "~int MyClass!" << endl;
    	}
    };
    
    int main()
    {
    	MyClass<char> mc0;
    	MyClass<int> mc1;	
    	return 0;
    }
    

    运行结果:

    T MyClass!
    int MyClass!
    ~int MyClass!
    ~T MyClass!
    

    萃取机制

    现在举一系列例子来说明萃取机制

    现在有两个类,需要完成相同的功能GetSum返回求和值

    //int类型
    class IntArray
    {
    public:
        IntArray()
        {
            a = new int[10];
            for (int i = 0; i < 10; ++i)
            {
                a[i] = i + 1;
            }
        }
        ~IntArray()
        {
            delete[] a;
        }
    
        int GetSum(int times)	//对整数求和
        {
            int sum = 0;
            for (int i = 0; i < 10; ++i)
                sum += a[i];
            cout << "int sum=" << sum << endl;
            return sum * times;
        }
    private:
        int *a;
    };
    
    //Float类型
    class FloatArray
    {
    public:
        FloatArray()
        {
            f = new float[10];
            for (int i = 1; i <= 10; ++i)
            {
                f[i - 1] = 1.0f / i;
            }
        }
        ~FloatArray()
        {
            delete[] f;
        }
        float GetSum(float times)	//对浮点数求和
        {
            float sum = 0.0f;
            for (int i = 0; i < 10; i++)
                sum += f[i];
            cout << "float sum=" << sum << endl;
            return sum * times;
        }
    private:
        float* f;
    };
    

    我们可以看到,这样写代码冗余度很高,一部分功能比如GetSum函数,两个类都有,能不能用一个类完成?

    先定义一个类,通过泛型,调用对应对象的GetSum函数得到结果。

    template<class T>
    class Apply
    {
    public:
        float GetSum(T& t, float inarg)
        {
            return t.GetSum(inarg);
        }
    };
    

    这种方法不能完全解决我们的问题(函数返回值和参数类型固定,就会导致异常),如何解决变化的输入输出参数?traits技术就能解决问题。

    template<class T>	//可以什么都不用写,说明定义了一个模板类
    class NumTraits
    {};
    
    //模板特化IntArray
    template<>
    class NumTraits<IntArray>
    {
    public:
        typedef int resulttype;
        typedef int inputargtype;
    };
    //模板特化FloatArray
    template<>
    class NumTraits<FloatArray>
    {
    public:
        typedef float resulttype;
        typedef float inputargtype;
    };
    
    template<class T>
    class Apply2
    {
    public:
        NumTraits<T>::resulttype GetSum(T& obj, NumTraits<T>::inputargtype inputarg)
        {
            return obj.GetSum(inputarg);
        }
    };
    
    int main()
    {
        IntArray intary;
        FloatArray floatary;
        Apply2<IntArray> ai2;  //采用萃取
        Apply2<FloatArray> af2; //采用萃取
        cout << "2整型数组的和3倍:" <<ai2.GetSum(intary,3) << endl;	//返回整形
        cout << "2浮点数组的和3.2倍:" << af2.GetSum(floatary,3.2f) << endl;	//返回浮点型
        return 0;
    }
    

    为什么两个类中都定义了resulttype和inputargtype,为什么要把返回类型、输入参数,都定义为相同的名称呢?因为为了编制模板类共同的调用接口做准备。

    为了简化Apply2函数的定义形式,再次巧妙运用typedef进行定义,代码如下,与原始功能相同。

    //泛型模板类
    template<class T>
    class NumTraits
    {};	//可以什么都不用写,说明定义了一个模板类
    
    template<> //模板特化
    class NumTraits<IntArray>
    {
    public:
        typedef int resulttype;
        typedef int inputargtype;
    };
    
    template<> //模板特化
    class NumTraits<FloatArray>
    {
    public:
        typedef float resulttype;
        typedef float inputargtype;
    };
    
    template<class T>
    class Apply2
    {
    public:
        typedef NumTraits<T>::resulttype result;
        typedef NumTraits<T>::inputpara input;
        
        result GetSum(T& obj, intput inputarg)
        {
            return obj.GetSum(inputarg);
        }
    };
    

    总结

    萃取机制在STL中被广泛运用,借助模板特化和和typedef可以将接口做到通用,降低了代码的冗余度,提高了代码的复用

  • 相关阅读:
    Windows搭建SkyWalking8.3环境进行JAVA应用性能监控及入门示例(使用Mysql持久化)
    使用JMeter进行压力测试
    IDEA2020.1使用LeetCode插件运行并调试本地样例
    centos7使用Minikube“快速搭建“出Kubernetes本地实验环境(踩坑集锦及解决方案)
    事务的隔离级别与所带来的问题
    深入理解HashMap第一篇
    LoadRunner 与浏览器兼容性
    互联网产品接入支付功能如何测试?
    基于AMF协议的Flex应用程序的性能测试
    centos+mono+nginx+jexus 搭建linux下c#运行环境测试
  • 原文地址:https://www.cnblogs.com/WindSun/p/11450701.html
Copyright © 2011-2022 走看看