函数模板以及类模板(C++)

模板编程

函数模板使用

直接上代码;

template<typename T>//只对下一个生效,在后面需要重新再定义模板,这里的T为泛型类型
T add(T a, T b)
{
	return a + b;
}
int main()
{

	double a = 0.555, b = 0.9;
	int ia = 4, ib = 6;
	std::cout << add(a, b)<<std::endl;
	std::cout<<add(ia , ib);
	return 0;
}
结果
1.455
10

函数模板格式:

template <模板参数表>

函数定义(形参表可以包含模板参数表里的参数)

template <typename T,typename U >//注意使用逗号隔开,每个参数前面都要加typename
template <typename T,class U >//class与template,用处相同

在函数模板这里,class不是指类,其作用与typename相同。

函数模板使用注意:

函数模板使用时,传递参数时,可以进行类型自动推导,但参数类型不自动转换,因此对于参数类型要求严格,比如下面这个例子就会报错。因为在模板中T类型由a、b类型确认,但所给a、b类型都不同导致T的类型不确定,直接报错

template<typename T>
T add(T a, T b)
{
	return a + b;
}
double add(double a,double b)
{
    return a+b+2;
}
///
double a = 0.555,c=0.1;int b = 9;
add(a,b)//此时会调用第二个add,因为普通函数会自动类型转换,而模板函数匹配不上。
add<>(a,c);//要用模板函数调用
add(s,c);//默认情况下,会先看普通函数,没有符合的。再看模板函数

函数模板的编译过程:

再编译器遇到函数模板时,并不会生成代码(不会编译),只检查语法错误;只有再实例化模板的一个特点版本时,编译器才会生成代码。

类模板使用

类模板的实例化:不同于函数模板使用时,类型会自动推导,类模板必须显式指定类型。见代码

template <class nn>
class farther
{
public:
	float sum;
	farther(nn a, nn b)
	{
		sum = a+ b;
	}
	void sdf(nn x);
    int get_sum();
    template<class tr>
	tr mlu(tr a);
};
template<class nn>//不能少!!
int farther<nn>::get_sum()//对于在外部定义的类模板成员函数,仍然需要加 template <class nn>,其它与普通成员函数定义相同
{
	return sum;
}
template <class nn>//不能少!!
void farther<nn>::sdf(nn x)//含有与类模板一样模板参数的成员函数
{
	++sum;
}
template<class nn>//即使是成员模板,所属的类模板的模板参数也不能少!!
template<class tr>//类模板自己的模板参数
tr farther<nn>::mlu(tr a)
{
	return a * a;
}

##############################################################
int x1 = 55, x2 = 15;
	farther<int>fa(x1,x2);//必须显示指定类型
	cout << fa.sum;//结果为70
string as = "sdf";
fa.sdf(as);//此处代码编译前不会报错,但编译后,就会报错,因为此时的泛型数据nn已经确定为整型
//而成员函数的数据类型与类模板是一样的
float mm = 5.5;
fa.sdf(mm);
cout << float(fa.sum);//此时输出为75,因为类型已经确定是int(此时的模板函数已经编译了,就和一般函数一样),所以虽然传递参数是float,但最后会类型转换为int;

类模板的成员函数:

由于类模板在实例化后,每个实例都有自己的类型版本,因此类模板的成员函数(j即使是普通函数)也会具有和类模板一样的模板参数,定义使用见上面代码。(最好把代码理解,看注释,已经能理解到,类模板与类成员函数的模板参数是一致的)。

成员模板(copy的C++ primer):一个类(无论是普通类,还是类模板)可以包含本身就是模板的成员函数,这就是成员模板(成员模板不能是虚函数)

普通类的成员模板

直接看代码,很简单

//普通类
class farther
{
  template<class tr>
	tr mlu(tr a);//成员模板声明
}
//成员模板
tr farther<nn>::mlu(tr a)
{
	return a * a;
}

类模板的成员模板

从上面代码,摘录部分:(具体见代码)

//类模板
template <class nn>
class farther
{
public:
	float sum;
	farther(nn a, nn b)
	{
		sum = a+ b;
	}
	void sdf(nn x);
    int get_sum();
    template<class tr>
	tr mlu(tr a);
};

//成员模板
template<class nn>//即使是成员模板,所属的类模板的模板参数也不能少!!
template<class tr>//类模板自己的模板参数
tr farther<nn>::mlu(tr a)
{
	return a * a;
}

类模板派生类

class child : public farther<int>
//这里int是对所继承类的模板参数类型确定
{
public:
	child(int x1,int x2):farther(x1,x2)
	{
		sum = x1 * x2; ;
	};
};

template <class XX>
class child2 : public farther<XX>
//此时派生类也是类模板,其模板参数设置与基类相同
{
public:
	child(XX x1, XX x2) :farther(x1, x2)
	{
		sum = x1 * x2; ;
	};
};


 * x2; ;
	};
};

template <class XX>
class child2 : public farther<XX>
//此时派生类也是类模板,其模板参数设置与基类相同
{
public:
	child(XX x1, XX x2) :farther(x1, x2)
	{
		sum = x1 * x2; ;
	};
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值