C++ 函数模板与类模板(使用 Qt 开发编译环境)
注意:本文中代码均使用 Qt 开发编译环境,如有疑问和建议欢迎随时留言。
模板是 C++ 支持参数化程序设计的工具,通过它可以实现参数多态性。所谓参数多态性,就是将程序所处理的对象的类型参数化,使得一段程序可以用于处理多种不同类型的对象。
函数模板
函数模板的定义形式是:
template <class T> // or template <typename T>
returnType functionName ( params ) {
// todo something
}
所有函数模板的定义都是用关键字 template 开始的,该关键字之后是使用尖括号 <> 括起来的类型参数表。每一个类型参数 T 之前都有关键字 class 或者关键字 typename,这些类型参数代表的是类型,可以是内部类型或自定义类型。这样,类型参数就可以用来指定函数模板本身的参数类型和返回值类型,以及声明函数中的局部变量。函数模板中函数体的定义方式与定义其它函数类似。
实例一:
#include <QCoreApplication>
#include <QDebug>
template < typename T >
T abs(T x) {
return x < 0 ? -x : x;
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
int n = -5;
double d = -5.5;
qDebug() << abs(n);
qDebug() << abs(d);
qDebug() << abs(d+n);
return a.exec();
}
运行结果:

实例二:
#include <QCoreApplication>
//#include <QDebug>
#include <iostream>
using namespace std;
template <typename T>
void outputArray(const T *P_aaray,const int count){
for(int i=0; i < count; i++) {
cout<<P_aaray[i]<<" ";
}
cout<<endl;
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
const int aCount = 8, bCount= 8, cCount = 20;
int aArray[aCount] = {1,2,3,4,5,6,7,8};
double bArray[bCount] = {1.1,2.2,3.3,4.4,5.5,6.6,7.7,8.8};
char cArray[cCount] = "Welcometo see you!";
cout <<"a Array contains: "<<endl;
outputArray(aArray,aCount);
cout <<"b Array contains: "<<endl;
outputArray(bArray,bCount);
cout <<"c Array contains: "<<endl;
outputArray(cArray,cCount);
return a.exec();
}
运行结果:

函数模板几点注意
① 如果在全局域中声明了与模板参数同名的对象函数或类型,则该全局名将被隐藏。例如,在下面的例子中tmp 的类型不是 double 而是模板参数 Type :
typedef double Type;
template <class Type>
Type min( Type a, Type b ) {
// tmp 类型为模板参数 Type
// 不是全局 typedef
Type tmp = a < b ? a : b;
return tmp;
}
② 在函数模板定义中声明的对象或类型不能与模板参数同名
template <class Type>
Type min( Type a, Type b ) {
// 错误: 重新声明模板参数 Type
typedef double Type;
Type tmp = a < b ? a : b;
return tmp;
}
③ 模板类型参数名可以被用来指定函数模板的返回位
// ok: T1 表示 min() 的返回类型,T2 和 T3 表示参数类型
template <class T1, class T2, class T3>
T1 min( T2, T3 );
④ 模板参数名在同一模板参数表中只能被使用一次,但是模板参数名可以在多个函数模板声明或定义之间被重复使用
// 错误: 模板参数名 Type 的非法重复使用
template <class Type, class Type>
Type min( Type, Type );
// ok: 名字 Type在不同模板之间重复使用
template <class Type>
Type min( Type, Type );
template <class Type>
Type max( Type, Type );
⑤ 如果一个函数模板有一个以上的模板类型参数则每个模板类型参数前面都必须有关键字 class 或 typename
// ok: 关键字 typename和 class 可以混用
template <typename T, class U>
T minus( T*, U );
// 错误: 必须是 <typename T, class U> 或 <typename T, typename U>
template <typename T, U>
T sum( T*, U );
⑥ 为了分析模板定义,编译器必须能够区分出是不是类型的表达式。对于编译器来说它并不总是能够区分出模板定义中的哪些表达式是类型(例如:如果编译器在模板定义中遇到表达式 Parm::name 且 Parm 这个模板类型参数代表了一个类那么 name 引用的是 Parm 的一个类型成员吗?)
template <class Parm, class U>
Parm minus( Parm* array, U value ) {
Parm::name * p; // 这是一个指针声明还是乘法乘法?
}
编译器不知道 name 是否为一个类型。因为它只有在模板被实例化之后才能找到 Parm 表示的类的定义。为了让编译器能够分析模板定义,用户必须指示编译器哪些表达式是类型表达式。告诉编译器一个表达式是类型表达式的机制是在表达式前加上关键字 typename 例如如果我们想让函数模板 minus() 的表达式 Parm::name 是个类型名因而使整个表达式是一个指针声明我们应如下修改:
template <class Parm, class U>
Parm minus( Parm* array, U value ) {
typename Parm::name * p; // ok: 指针声明
}
如上面的几个例子中所示,关键字 typename 也可以被用在模板参数表中以指示一个模板参数是一个类型。
⑦ 如同非模板函数一样,函数模板也可以被声明为 inline 或 extern 的。此时,应该把指示符放在模板参数表后面而不是在关键字 template 前面。
// ok: 关键字跟在模板参数表之后
template <typename Type>
inline
Type min( Type, Type );
类模板
使用类模板使用户可以为类声明一种模式,使得类中的某些数据成员、某些成员函数的参数、某些成员函数的返回值能取任意类型(包括系统预定义的和用户预定义的)。由于类模板需要一种或多种类型参数,所以类模板也常称为参数化类。
类模板声明的语法形式是:
template<模板参数表>
class类名{
//类成员声明
}
如果需要在类模板以外定义其成员函数,则需要采用以下形式:
template<模板参数表>
类型名类名<T>::函数名(参数表)
“模板参数表”由用逗号分隔的若干类型标识符或常量表达式构成,其内容包括:
(1)class 或 typename 标识符,指明可以接受一个类型的参数。
(2)类型说明符 标识符,指明可以接受一个由“类型说明符”所规定类型的常量作为参数。
“模板参数表”同时包含上述多项内容时,各项内容以逗号分隔。应该注意的是,模板类的成员函数必须是模板函数。
一个类模板声明自身不产生代码,他说明了类的一个家族。只有当它被其它代码引用时,模板才根据引用的需要产生代码。
使用一个模板类来建立对象时,应按如下形式声明:
模板<模板参数表> 对象名1,…,对象名n;
使用实例:
#include <QCoreApplication>
#include <QDebug>
struct Student {
int id;
float gpa;
};
template <class T>
class Store{
public:
Store(void);
T GetElem(void);
void PutElem(T x);
private:
T item;
int haveValue;
};
template <class T>
Store<T>::Store(void)
: haveValue(0)
{
}
template <class T>
T Store<T>::GetElem(void) {
if (haveValue == 0) {
qDebug() << "No item present!";
exit(1);
}
return item;
}
template <class T>
void Store<T>::PutElem(T x){
haveValue++;
item = x;
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Student g ={1000,23};
Store<int> S1,S2;
Store<Student> S3;
Store<double> D;
S1.PutElem(3);
S2.PutElem(-7);
qDebug() << S1.GetElem() << " " << S2.GetElem();
S3.PutElem(g);
qDebug() << "The student id is "<< S3.GetElem().id;
qDebug() << "Retrieving object D ";
qDebug() << D.GetElem();
return a.exec();
}
输出结果:

注意:本文中代码均使用 Qt 开发编译环境,如有疑问和建议欢迎随时留言。
作者:赵者也
链接:http://www.jianshu.com/p/4c64d1b567a7
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
https://www.cnblogs.com/aademeng/articles/7265011.html
C++ 函数模板与类模板(使用 Qt 开发编译环境)的更多相关文章
- [Reprint] C++函数模板与类模板实例解析
这篇文章主要介绍了C++函数模板与类模板,需要的朋友可以参考下 本文针对C++函数模板与类模板进行了较为详尽的实例解析,有助于帮助读者加深对C++函数模板与类模板的理解.具体内容如下: 泛型编程( ...
- C++_进阶之函数模板_类模板
C++_进阶之函数模板_类模板 第一部分 前言 c++提供了函数模板(function template.)所谓函数模板,实际上是建立一个通用函数,其函数类型和形参类型不具体制定,用一个虚拟的类型来 ...
- C++复习:函数模板和类模板
前言 C++提供了函数模板(function template).所谓函数模板,实际上是建立一个通用函数,其函数类型和形参类型不具体指定,用一个虚拟的类型来代表.这个通用函数就称为函数模板.凡是函数体 ...
- 【校招面试 之 C/C++】第2题 函数模板、类模板、特化、偏特化
1.C++模板 说到C++模板特化与偏特化,就不得不简要的先说说C++中的模板.我们都知道,强类型的程序设计迫使我们为逻辑结构相同而具体数据类型不同的对象编写模式一致的代码,而无法抽取其中的共性,这样 ...
- C++解析(26):函数模板与类模板
0.目录 1.函数模板 1.1 函数模板与泛型编程 1.2 多参数函数模板 1.3 函数重载遇上函数模板 2.类模板 2.1 类模板 2.2 多参数类模板与特化 2.3 特化的深度分析 3.小结 1. ...
- C++学习之函数模板与类模板
泛型编程(Generic Programming)是一种编程范式,通过将类型参数化来实现在同一份代码上操作多种数据类型,泛型是一般化并可重复使用的意思.泛型编程最初诞生于C++中,目的是为了实现C++ ...
- C++ 模板常见特性(函数模板、类模板)
背景 C++ 是很强大,有各种特性来提高代码的可重用性,有助于减少开发的代码量和工作量. C++ 提高代码的可重用性主要有两方面: 继承 模板 继承的特性我已在前面篇章写过了,本篇主要是说明「模板」的 ...
- C++进阶-1-模板基础(函数模板、类模板)
C++进阶 模板 1.1 函数模板 1 #include<iostream> 2 using namespace std; 3 4 // 模板 5 6 // 模板的简单实例 7 // 要求 ...
- 学习C++模板,类模板
当我们使用向量时,会经常使用形如:vector<int> a的式子.这个表达式就是一个类模板实例化的例子,vector是一个类模板,我们给他传递模板参数(见<>里),然后创建一 ...
随机推荐
- 【Linux】 JDK安装及配置 (linux-tar.gz版)
安装环境:Linux(CentOS 7 64位 版) JDK安装:tar.gz为解压后就可以使用的版本,这里使用jdk-8u211-linux-x64.tar.gz版,安装到/usr/java/(us ...
- Spring框架系列(六)--事务Transaction
本文绝大部分内容为转载,原文地址:https://blog.csdn.net/trigl/article/details/50968079 除此之外,后面还有延伸内容 事务在企业日常开发中几乎是一定会 ...
- Java必知必会的20种常用类库和API
转载:https://blog.csdn.net/u011001084/article/details/79216958 个人感觉工具类对日常开发是很重要的,所以推荐一下这篇文章,虽然有的类库过时了 ...
- 重启rsyncd
systemctl restart rsyncd.service
- top命令的用法
top命令的用法 2018年07月15日 09:50:04 zhuoya_ 阅读数:1858 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/z ...
- HDU - 2044 - 一只小蜜蜂...(dp)
题意: 如题 思路: 仔细观察图 1-4和3-6其实是一样的答案,那么所有的方案都可以相减,意思为全部转化为从1开始 剩下的就是观察规律,仔细观察5号,能到5号蜂房的只有3和4,3和4到5号蜂房只有一 ...
- ecshop笔记
***ecshop在线入门手册***:http://book.ecmoban.com/ 解决ecshop与jquery冲突问题1.修改文件:/js/transport.js在文件最底部增加代码: if ...
- db2层级查询
CREATE VIEW v_orgtype99 asSELECT t1.SYS_ORG_TYPE_NAME top_name1, t2.SYS_ORG_TYPE_NAME top_name2, --若 ...
- The C Programming Language-4.1
下面是c程序设计语言4.1代码以及我的一些理解 strindex函数,通过嵌套两次循环,在s[ ]和t[ ]两个数组对映元素相等且t[ ]尚未遍历完毕的情况下,不断循环,最终返回正数或-1 代码如下 ...
- 一:安装centos 7最小编程环境 xfce桌面
1, u盘制作安装盘------------------------------------------------------安装时, table或者e进入编辑选项 如果不知道你的u盘的盘符 ...