17. 模板

调用模板函数时,编译器根据调用参数推断出模板参数,用来实例化一个特定版本的函数。

template<typename T>
T Add(T a, T b) {
	return a + b;
}

template<typename T,typename U>
T Add(T a, U b) {
	return a + b;
}

//模板特例化,template后跟一对空的<>,并为所有模板参数提供实参
template<>
char *Add(char *a, const char *b) {
	return strcat(a, b);
}

int Add(int, int) {
	cout << "!!!" ;
	return 0;
}

int  main() {
	
	Add(1, 2);//普通函数优先于模板
	Add(1.2, 2.3);//编译器自动推断模板参数类型
	Add(1LL, 2);//编译器自动推断模板参数类型
	Add(1, 'a');//编译器自动推断模板参数类型
	Add<double, long long>(1, 'a');//指定类型
	
	char buff[100] = "Hello";
	Add(buff, "World");//特例化的优于普通的模板
	
	return 0;
}

  

模板再使用时才会实例化,产生对应类型的二进制代码。如果没有实例化,则编译生成的obj文件中不存在模板相关的代码,所以模板的声明和实现都放在头文件中。否则会发生链接错误,因为只有声明,没有实现。

 

成员函数模板

 

class Foo {
public:
	template<typename T>
	void Print(T val) {
		cout << n << " " << val;
	}
private:
	int n = 1;
};


int  main() {
	
	Foo foo;
	foo.Print(1);//自动推断参数类型
	foo.Print(1.2);//自动推断参数类型
	foo.Print<double>(1.2);//显示指定参数类型
	
	return 0;
}

 

类模板:

template<typename T>
class Foo {
public:
	Foo(T val);

	void Print(T val) {
		cout << n << " " << val << endl;
	}
private:
	T n;
};
template<typename T>
Foo<T>::Foo(T val) :n(val) {}


template<>
class Foo<char> {//类模板特例
public:
	Foo(char val);

	void Print(char val) {
		cout << "类模板特例:";
		cout << n << " " << val << endl;
	}
private:
	char n;
};
Foo<char>::Foo(char val):n(val) {}

template<typename T>
class Child :public Foo<T> {//继承,Child也是模板
public:
	Child(T val) :Foo<T>(val) {

	}
};

class Child2 :public Foo<double> {//Child2不是模板,是具体的类
public:
	Child2(double val) :Foo<double>(val) {

	}
};
int  main() {
	
	Foo<int> foo(11);//类模板必须提供显示模板实参,编译器无法推导
	foo.Print(12);

	Foo<double> foo1(1.222);//类模板必须提供显示模板实参,编译器无法推导
	foo1.Print(3.14);

	Foo<char> foo2('A');//类特例
	foo2.Print('B');
	
	Child<int> child(1);

	Child2 child2(111);

	return 0;
}

  

 

posted @ 2020-05-27 09:03  八转达人  阅读(238)  评论(0编辑  收藏  举报