C++模板函数示例

Posted Roam-G

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++模板函数示例相关的知识,希望对你有一定的参考价值。

9.1//求绝对值函数的模板

编译器从调用abs()时实参的类型,推导出函数模板的类型参数。例如,对于调用表达式abs(n),由于实参n为int型,所以推导出模板中类型参数T为int。

当类型参数的含义确定后,编译器将以函数模板为样板,生成一个函数:int abs(int x) { return x < 0 ? –x : x;}

//求绝对值函数的模板
#include <iostream>
using namespace std;

template<typename T>
T abs(T x) {
	return x < 0 ? -x : x;
}
int main() {
	int n = -5;
	double d = -5.5;
	cout << abs(n) << endl;
	cout << abs(d) << endl;
	return 0;
}

例9-1模板函数示例

#include <iostream>
using namespace std;

template<class T> //定义类模板
void outputArray(const T* array, int count) {
	for (int i = 0;i < count;i++) {
		cout << array[i] << " ";

	}
	cout << endl;
}
int main() {

	const int A_COUNT = 8, B_COUNT = 8, C_COUNT = 20;
	//定义int数组
	int a[A_COUNT] = { 1,2,3,4,5,6,7,8 };
	//定义double数组
	double b[B_COUNT] = { 1.1,2.2,3.3,4.4,5.5,6.6,7.7,8.8 };

	//定义char数组
	char c[C_COUNT] = "Welcome to see you!";


	cout << "a array contains:" << endl;
	//调用类模板
	outputArray(a, A_COUNT);

	cout << "b array contains:" << endl;
	//调用类模板
	outputArray(b, B_COUNT);

	cout << "c array contains:" << endl;
	//调用类模板
	outputArray(c, C_COUNT);
	return 0;


}

类模板的作用

使用类模板使用户可以为类声明一种模式,使得类中的某些数据成员、某些成员函数的参数、某些成员函数的返回值,能取任意类型(包括基本类型的和用户自定义类型)。

类模板:

template <模板参数表>

class 类名

{类成员声明}

如果需要在类模板以外定义其成员函数,则要采用以下的形式:

template <模板参数表>

类型名 类名<模板参数标识符列表>::函数名(参数表)

例9-2

//9-2.cpp类模板示例

#include <iostream>
#include <cstdlib>
using namespace std;
//学生结构体
struct Student
{
	int id; //学号
	float gpa; //学分
};

template<class T>
//类模板 实现对任意 类型的数据进行存取。
class Store {
private:
	T item;  //存放任意类型的数据
	bool haveValue; //标记item是否已经被存入数据
public:
	//无参构造
	Store(); 
	T& getElem();  //提取数据函数
	void putElem(const T& x); //存入数据函数
};

//默认构造函数的实现
template<class T> 
Store<T>::Store():haveValue(false){}

//提取函数的实现
template<class T>
T& Store<T>::getElem() {
	//如果试图提取未初始化的数据,则终止程序
	if (!haveValue) {
		cout << "No item present!" << endl;
		//使程序完全退出,返回到操作系统
		exit(1);
	}
	//返回item中的数据
	return item;
}

//存入数据函数的实现
template<class T>
void Store<T>::putElem(const T& x) {
	//将haveValue设置为 true ,表示 已经存入数据
	haveValue = true;
	item = x;//将x存入item
}

int main() {
	Store<int> s1, s2;
	s1.putElem(3);
	s2.putElem(-7);
	cout << s1.getElem() << "  " << s2.getElem() << endl;

	Student g = { 1000,23 };
	Store<Student> s3;
	s3.putElem(g);
	cout << "The student id is  " << s3.getElem().id << endl;

	Store<double> d;
	cout << "Retrieving object D..."<<endl;
	cout <<d.getElem()<<endl;
	//由于 d 未 经过 初始化,会导致程序终止
	return 0;

}

例9-3 动态数组类模板程序

#ifndef ARRAY_H
#define ARRAY_H
#include <cassert>

//数组类模板定义
template<class T>
class Array {
private:
	T* list; //存放动态分配的数组内存首地址
	int size; //数组元素个数
public:

	Array(int sz = 50); //构造函数
	Array(const Array<T>& a); //复制构造函数
	~Array(); //析构函数

	//重载 =
	Array<T>& operator = (const Array<T>& rhs);

	//重载 []
	T& operator [](int i);
	const T& operator [](int i)const;

	//重载 到T*类型的转换
	operator T* ();
	operator const T* ()const;

	int getSize() const; //取数组的大小
	void resize(int sz); //修改数组的大小
};

//构造函数
template <class T> Array<T>::Array(int sz) {
	assert(sz >= 0); //sz 必须非负
	size = sz;
	list = new T[size]; //动态分配size个T类型的元素空间
}

//析构函数
template <class T> Array<T>::~Array() {
	delete[]list;//释放数组
}

//复制构造函数
template <class T> Array<T>::Array(const Array<T>& a) {
	//从 对象x取得数组的大小,并赋值为当前的对象成员
	size = a.size;

	//为对象 申请 内存并进行出错检查
	list = new T[size];
	//从对象  x 复制数组元素到本对象
	for (int i = 0;i < size;i++) {
		list[i] = a.list[i];
	}
}
//重载 = 运算符 将 对象 rhs 赋值为本对象,实现对象之间的整体赋值
template<class T>
Array<T>& Array<T>::operator = (const Array<T>& rhs) {
	if (&rhs != this) {
		//如果 本对象中数组大小和rhs不同,则删除数组原有内存,并重新分配
		if (size != rhs.size){
			delete[]list;
			size = rhs.size;
			list = new T[size];
		}
		//从对象x复制数组元素到本对象
		for (int i = 0;i < size;i++) {
			list[i] = rhs.list[i];
		}
	}
	//返回当前对象的引用
	return *this;
}

//重载下标运算符,实现和普通数组一样通过下标访问元素,并且具有越界检查功能
template<class T>
T& Array<T>::operatorp[](int n) {
	//检查下标是否越界
	assert(n >= 0 && n < size);
	//返回下标为n 的数组元素
	return list[n];
}
template<class T>
const T& Array<T>::operator[] (int n)const {
	assert(n >= 0 && n < size);
	return list[n];

}
//重载指针转换运算符,将array类的对象名 转换为 T 类型的指针
template<class T>
Array<T>::operator T* () {
	return list;//返回当前 对象中私有数组的首地址

}
template<class T>
Array<T>::operator const T* ()const {
	return list;
}
//取当前数组的大小
template<class T>
int Array<T>::getSize()const {
	return size;
}

//将数组大小修改为sz
template<class T>
void Array<T>::resize(int sz) {
	//检查sz是否非负
	assert(sz >= 0);
	//如果指定的大小  和原有的大小一样,
	//什么也不用做
	if (sz == size) {
		return;
	}
	//申请新的 数组内存
	T* newList = new T[sz];
	//将sz和size比较中娇小的一个赋值给n
	int n = (sz < size) < sz:size;
	//将 原有数组中前n个元素复制到新数组中
	for (int i = 0;i < n;i++) {
		newList[i] = list[i];
	}
	//删除原有数组
	delete[] list;
	//使list 指向新的数组
	list = newList;
	//更行size
	size = sz;
}
#endif //ARRAY_H

C++ 常量

常量可以是任何的基本数据类型,可分为整型数字、浮点数字、字符、字符串和布尔值

整数常量可以是十进制、八进制或十六进制的常量。

前缀指定基数:0x 或 0X 表示十六进制,0 表示八进制,不带前缀则默认表示十进制。

整数常量也可以带一个后缀,后缀是 U 和 L 的组合,U 表示无符号整数(unsigned),L 表示长整数(long)。后缀可以是大写,也可以是小写,U 和 L 的顺序任意

浮点常量由整数部分、小数点、小数部分和指数部分组成。您可以使用小数形式或者指数形式来表示浮点常量。

当使用小数形式表示时,必须包含整数部分、小数部分,或同时包含两者。当使用指数形式表示时, 必须包含小数点、指数,或同时包含两者。带符号的指数是用 e 或 E 引入的。

C++强制类型转换操作符 static_cast

static_cast是一个强制类型转换操作符。强制类型转换,也称为显式转换,C++中强制类型转换操作符有static_cast、dynamic_cast、const_cast、reinterpert_cast四个。本节介绍static_cast操作符。

C++强制类型转换操作符 static_cast - melonstreet - 博客园

cout<<" Score"<<static_cast<float>(numCorrect)/NUM_QUES*100<<"%";

cout<<" Score"<<numCorrect/NUM_QUES*100<<"%";

以上是关于C++模板函数示例的主要内容,如果未能解决你的问题,请参考以下文章

调用模板化成员函数:帮助我理解另一个 *** 帖子中的代码片段

我的Android进阶之旅NDK开发之在C++代码中使用Android Log打印日志,打印出C++的函数耗时以及代码片段耗时详情

C++入门C++ 函数模板&类模板

如何将右值引用参数传递给 C++ 中的模板 operator() 函数?

C#常用代码片段备忘

为啥此代码有效(具有无效非模板函数的 C++ 模板类)? [复制]