写在前面:感谢GeekBand提供这样好的学习机会,让我在繁忙的工作之余可以学习巩固c++知识。以下是边学边记的一些扩展点。分享给大家。
这次关于“Traits”的使用,是很实用的。由于C++本身没有像C#, java 中类似类型的判断,所以需要自己来写。这次任务是写一个Caltulator类的函数,但是要针对不同的数据类型来处理。
假设有个计算类Calculator,它要处理int, long, float, double等数值类型。用模板实现GetLimit()方法,获得每种类型的数值的上限LIMIT,比如int的上限是100,long的上限是 1000,float的上限是999.99,double的上限是888.8888888等等。
这样的话,我们可以有两种实现思路:用类(class)或者是结构体(struct)
#include <iostream> // 为了输出
#include <iomanip> // 为了控制输出效果
using namespace std;
//如果用结构体,需要这样处理
template <typename T>
struct CalculatorTraits { };
//先定义一个针对int的Trait。类似的,可以特化出针对其他类型的Trait。
template< >
class CalculatorTraits<int>
{
public:
typedef int ValueType;
CalculatorTraits() : limit(100) { }
ValueType getLimit() { return limit; }
private:
ValueType limit;
};
// 如何放置在Calculator类中。
template <typename T>
struct Calculator {
typename CalculatorTraits<T>::ReturnType GetLimit() {
return CalculatorTraits<T>::LIMIT;
}
};
//如果特化一个类,需要这样来处理: 声明一个含有template<>的类,即空参数列表
template<typename T>
class CalculatorTraits {};
//再显示指明类型,先看一个针对int类型的例子,你可以仿照这个推理出其他类型的代码
template<>
struct CalculatorTraits<int> {
typedef int ReturnType;
static constexpr ReturnType LIMIT = 100;
};
//下面是在Calculator类中,怎么放置这个模板,以达到调用的目的。
template <typename T>
class Calculator
{
public:
typedef CalculatorTraits<T> CalTraits;
typedef typename CalTraits::ValueType ValueType;
ValueType GetLimit()
{
CalculatorTraits<T> calTraits;
return calTraits.getLimit();
}
};
不管你用类还是结构体,下面的调用方法是一样的。注意,在输出的时候需要用setprecision(10) 来控制显示。否则的话,你就会被四舍五入的显示困扰。
int main() {
Calculator<int> cInt;
Calculator<long> cLong;
Calculator<float> cFloat;
Calculator<double> cDouble;
cout << "GetLimit(int):"<<cInt.GetLimit() << endl;
cout << "GetLimit(long):" << cLong.GetLimit() << endl;
cout << "GetLimit(float):" << cFloat.GetLimit() << endl;
cout << "GetLimit(double):" <<setprecision(10) << cDouble.GetLimit() << endl;
return 0;
}