1.1 类模板
1.1.1思考
- 在C++中是否能够将泛型的思想应用于类?
1.1.2
- 一些类主要用于存储和组织数据元素
- 类中数据组织的方式和数据元素的具体类型无关
- 如: 数组类,链表类,Stack类,Queue类等
- C++中将模板的思想应用于类,使得类的实现不关注数据元素的具体类型,而只关注类所需要实现的功能
1.1.3 C++中的类模板
- 以相同的方式处理不同的类型
- 在类声明前使用template进行标识
- 用于说明类中使用泛指类型T
template <typename T>
class Operator
{
public:
T op(T a, T b);
};
1.1.4 C++中的类模板的应用
- 只能显示指定具体类型,无法自动推导
- 使用具体类型 定义对象
Operator<int> op1;
Operator<string> op2;
int i = op1.op(1,2);
string s = op2.op("zhagnsan","safd");
1.1.5 C++中的类模板的应用
- 声明的泛指类型T可以出现在类模板的任意地方
- 编译器对类模板的处理方式和函数模板相同
- 从类模板通过具体类型产生不同的类
- 在声明的地方对类模板代码本身进行编译
- 在使用的地方对参数替换后的代码进行编译
template < typename T >
class Operator
{
public:
T add(T a, T b)
{
return a + b;
}
T minus(T a, T b)
{
return a - b;
}
T multiply(T a, T b)
{
return a * b;
}
T divide(T a, T b)
{
return a / b;
}
};
/*
string operator-(string& l, string& r)
{
return "Minus";
}
*/
int main()
{
Operator<int> op1;
cout << op1.add(1, 2) << endl;
Operator<string> op2;
cout << op2.add("Zhang", "San") << endl;
//cout << op2.minus("Zhang", "San") << endl; // string 中没有定义减号操作符的重载,会报错,但是当我重载字符串的减法操作以后就不会报错
return 0;
}
1.1.6类模板的工程应用
- 类模板
必须在头文件中定义 - 类模板
不能分开实现在不同的文件中 - 类模板外部定义的成员函数需要加上
模板<>声明
template < typename T >
class Operator
{
public:
T add(T a, T b);
T minus(T a, T b);
T multiply(T a, T b);
T divide(T a, T b);
};
template < typename T >
T Operator<T>::add(T a, T b)
{
return a + b;
}
template < typename T >
T Operator<T>::minus(T a, T b)
{
return a - b;
}
template < typename T >
T Operator<T>::multiply(T a, T b)
{
return a * b;
}
template < typename T >
T Operator<T>::divide(T a, T b)
{
return a / b;
}
- 注意 是
Operator<T>::divide注意中间的<T>
1.2 类模板深度解析
1.2.1
- 类模板可以定义任意多个不同的类型参数
template
<typename T1,typename T2>
class Test
{
public:
void add(T1 a ,T2 b);
};
1.2.2类模板 特化
- 类模板可以被特化
- 指定类模板的特定实现
- 部分类型参数必须显示指定
- 根据类型参数分开实现类模板
特化前
template
<typename T1,typename T2>
class Test
{
};
特化后- 特化后,当两个类型相同的时候,编译器会优先选择特化后的类型实现
- 编译器会理解为这两个模板是一个类的模板
template
<typename T>
class Test <T, T>
{
};
1.2.3 类模板的特化类型
- 部分特化 - 用特定规则约束类型参数
- 完全特化 - 完全显示指定类型参数
- 特化前
template
<typename T1 ,typename T2>
class Test
{
}
- 特化后
template
<>
class Test <int ,int >
{}
1.2.4 类模板的特化示例
template <typename T1,typename T2>
class Test
{
public:
void add(T1 a, T2 b)
{
cout<<"void add(T1 a, T2 b)"<<endl;
cout<< a+ b<<endl;
}
};
template <typename T1,typename T2>
class Test <T1*,T2*>
{
public:
void add(T1* a, T2 * b)
{
cout<<"void add(T1* a, T2 * b)"<<endl;
cout<<*a + *b<<endl;
}
};
template <typename T>
class Test <T,T>
{
public:
void add(T a, T b)
{
cout<<"void add(T a, T b)"<<endl;
cout<< a+ b<<endl;
}
void print()
{
cout<<"class Test <T,T>"<<endl;
}
};
template <>
class Test<void * ,void*>
{
public:
void add(void * a, void * b)
{
cout<<"void add(void * a, void * b)"<<endl;
cout<<"error to add void * parameter...."<<endl;
}
};
int main()
{
Test<int ,double> t1;
t1.add(2,3.5);
Test<int ,int> t2;
t2.add(1,2);
Test<void *,void*> t3;
t3.add(NULL,NULL);
Test<int *,double*> t4;
int a =3;
double b =4.5;
t4.add(&a,&b);
return 0;
}

1.2.4 类模板的特化注意事项
- 特化只是模板的分开实现
- 本质试试同一个类模板
- 特化类模板的是使用方式是统一的
- 必须显示指定每一个类型参数
1.3 重定义和特化
1.3.1重定义和特化的不同
- 重定义
- 一个类模板和一个新类(或者两个类模板)
- 使用的时候需要考虑如何选择的问题
- 特化
- 以统一的方式使用类模板和特化类
- 编译器自动优化选择特化类
1.3.2 函数模板只支持类型参数完全特化
template <typename T>
bool equal(T a,T b)
{
cout<<"bool equal(T a,T b)"<<endl;
return a == b;
}
template <>
bool equal<double>(double a, double b)
{
const double v =0.000000000001;
cout<<"bool equal<double>(double a, double b)"<<endl;
if(a-b < v)
{
return true;
}
else{
return false;
}
}
bool equal(double a,double b)
{
const double v =0.000000000001;
cout<<"bool equal(double a,double b)"<<endl;
if(a-b < v)
{
return true;
}
else{
return false;
}
}
int main()
{
equal(1,1);
equal(1.1,1.1);
equal<>(1.1,1.1);
return 0;
}

参考一 : 狄泰软件课程
如有侵权:请联系邮箱 1986005934@qq.com

被折叠的 条评论
为什么被折叠?



