2_4_1 函数模板、类模板

4_1_函数模板.cpp

#include "hjcommon.hpp"

using namespace std;
HJ_NS_USING

HJ_NS_BEGIN
// 类型参数的函数模板,类型 T 可以用任意字符或字符串代替
template<typename T> // 可以使用typename或class,甚至可以两者混用。多个模板参数用 , 隔开。模板参数可以传递类型参数,也可以传递非类型参数(值)
T add(T a, T b)
{
	return a+b;
}
// 非类型参数的函数模板
template<int a, int b> // 这种非类型模板参数的值,或者是用户提供的,或者是编译器提供的。 这些值必须是常量表达式
int jian()
{
	return a-b;
}
// 类型参数与非类型参数的函数模板
template<typename T, int a, int b>
static inline int jia(T t) // 模板函数可以内联,也可以 static
{
	return (int)t + a + b;
}
// 自动推导
template<unsigned L1, unsigned L2> // unsigned L1表示无符号的整型,可以不把数据类型写全,编译器会自动推导。。
int cmp(const char(&str1)[L1], const char(&str2)[L2]) // const char(&str1)[5] = "some"; // 字符数组的const左值引用
{
	return strcmp(str1, str2); // strcmp 两个字符串相同返回0,否则非0
}
HJ_NS_END

int main_2_4_1(int argc, char *argv[])
{
	// 类型参数的模板函数
	int ret = add(2, 3); // 可以,编译器能自动类型推导
//	ret = add(2, 3.f); // 不可以,自动推导失败
	ret = add<>(2, 3); // 可以
	ret = add<int>(2, 3); // 可以

	// 非类型参数的模板函数
	ret = jian<2, 3>(); // 显式的提供模板参数, <> 中给定

	// 类型参数与非类型参数的函数模板
	ret = jia<double, 2, 3>(1);

	// 自动推导
	ret = cmp("some", "som"); // 可以,参数的字符串长度编译器会自动推导
	ret = cmp<5, 4>("some", "som"); // 可以,手动给定字符串的长度
//	ret = cmp<6, 4>("some", "som"); // 不可以,字符串长度不对
	cout << ret << endl;
	// 当定义模板的时候,编译器不会生成模板的代码,只有有用户调用的时候,编译器才会生成对应的模板代码, 所以模板一般写在头文件里,而且写在头文件里也不会造成重复定义

	return 0;
}

4_2_类模板.cpp

#include "hjcommon.hpp"

using namespace std;
HJ_NS_USING

HJ_NS_BEGIN

template<typename T=int, int size=10> // 类模板,c++11中模板函数与模板类的类型参数与非类型参数都可以给默认值的,c++98只允许模板类可以有默认参数
class myvector
{
public:
	typedef T* myiterator; // 这样定义的,myiterator 称为类的类型成员,当类的类型成员在类的外部或类的函数实现处使用,那么需要用 类名<>::类的类型成员 格式使用

	myvector(); // 类模板中所有函数如果在头文件声明时就写函数体,可以按照正常函数的写法
	myvector& operator=(const myvector &vec); // 函数声明时类名后加不加 <T, size> 都可以

	myiterator mybegin(); // 模板类的成员,只有用户实例化后有使用,才会被编译器把该成员加进模板类中
	myiterator myend();

	void func() { cout << "func." << endl; }
};
template<typename T, int size> // 这里size可以不用带上默认值
myvector<T, size>::myvector() // 模板类的函数实现如果另写在源文件中,那么需要加上模板类的模板,同时类名后需要带上 <所有模板参数>
{
	cout << "no arg constructor. size=" << size << endl;
}
template<typename T, int size>
myvector<T, size>& myvector<T, size>::operator=(const myvector &vec) // 参数 const myvector &vec 加不加 <T, size> 都可以
{
}
template<typename T, int size>
// 类的类型成员在函数声明外的函数实现处使用时,需要给函数加上 typename 修饰,否则编译报错
// 当函数(包括全局函数、类成员函数)的返回值类型为类的类型成员时,需要用 typenmae 告诉编译器这里是类的类型成员。这里的typename不能用class取代
// 总结:类的类型成员在使用的时候,前面都应该加上 typename 修饰
typename myvector<T, size>::myiterator myvector<T, size>::mybegin()
{
}

HJ_NS_END

int main_2_4_2(int argc, char*argv[])
{
	myvector<> vec1; // 可以,类模板使用时,必须带上<>,如果模板参数都有默认值,那么可不提供参数
	myvector<float> vec2; // 可以
	myvector<String, 100> ls; // 可以
	ls.func();

	// float、double、类类型 都不可以作为函数模板与类模板的非类型模板参数

	return 0;
}

4_3.cpp

#include "hjcommon.hpp"

using namespace std;
HJ_NS_USING

HJ_NS_BEGIN

static int add(int a, int b)
{
	int ret = a+b;
	cout << "add. ret=" << ret << endl;
	return ret;
}
class A
{
public:
	A() { cout << "no arg constructor." << endl; }
	A(const A &a) { cout << "copy constructor." << endl; }

	int operator()(int a, int b) const
	{
		int ret = a+b;
		cout << "operator(). ret=" << ret << endl;
		return ret;
	}
};
//template<typename T, typename F=int(*)(int, int)> // 另一种写法,模板参数默认值为函数指针类型
//static void testFunc(const T &a, const T &b, F funcPoint=add)
template<typename T, typename F=A> // 如果类类型为模板参数的默认值,那么模板函数的对应的形参也需要给默认值
static void testFunc(const T &a, const T &b, F funcPoint=F()) // 默认参数s
{
	funcPoint(a, b); // 函数调用,这里表示类型F是一个函数指针类型,如果一个类重载了 operator() 运算符,那么该类也可以当作是函数指针的数据类型,该类的对象可称为可调用对象
}

HJ_NS_END

int main_2_4_3(int argc, char *argv[])
{
	/* 打印:
		add. ret=4
		no arg constructor.
		copy constructor.
		operator(). ret=4
		no arg constructor.
		operator(). ret=4
		no arg constructor.
		operator(). ret=4
	 */
	testFunc(1, 3, add);
	A a;
	testFunc(1, 3, a);
	testFunc(1, 3, A()); // 相比上句代码,这里不会再多调用一次拷贝构造函数,即少一个临时对象的产生
	testFunc(1, 3); // 模板函数添加默认参数后,打印与上句代码一样
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值