C++进阶剖析( 二十五)之类模板

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值