C++:类模板与模板类
6.3 类模板和模板类
所谓类模板,实际上是建立一个通用类,其数据成员、成员函数的返回值类型和形参类型不具体指定,用一个虚拟的类型来代表。使用类模板定义对象时,系统会实参的类型来取代类模板中虚拟类型从而实现了不同类的功能。
定义一个类模板与定义函数模板的格式类似,必须以关键字template开始,后面是尖括号括起来的模板参数,然后是类名,其格式如下:
template <typename 类型参数>
class 类名{
类成员声明
};
或者
template <class 类型参数>
class 类名{
类成员声明
};
(1)template:是一个声明模板的关键字,它表明声明一个模板
(2)类型参数:通常用C++标识符表示,如T、Type等,实际上是一个虚拟的类型名,现在未指定它是哪一种具体的类型,但使用类模板时,必须将类型参数实例化。
(3)typename和class的作用相同,都是表示其后面的参数是一个虚拟的类名(即类型参数).
在类声明中,欲采用通用数据类型的数据成员、成员函数的参数或返回类型前面需要加上类型参数。
如建立一个用来实现求两个数最大值的类模板
template<typename T> //模板声明,其中T为类型参数
class Compare{
public:
Compare(T i,T j)
{
x = i;
y = j;
}
T max()
{
return (x>y)?x:y;
}
private:
T x,y;
};
用类模板定义对象时,采用以下形式:
类模板名<实际类型名>对象名[(实参表列)];
因此,使用上面求最大值的类型模板的主函数可写成:
int main()
{
Compare<int>com1(,);
Compare<double>com2(12.34,56.78);
Compare<char>com3('a','x');
cout<<"其中的最大值是:"<<com1.max()<<endl;
cout<<"其中的最大值是:"<<com2.max()<<endl;
cout<<"其中的最大值是:"<<com3.max()<<endl;
return ;
}
//例6.6 类模板compare的使用举例
#include<iostream.h>
template<typename T> //模板声明,其中T为类型参数
class Compare{
public:
Compare(T i,T j)
{
x = i;
y = j;
}
T max()
{
return (x>y)?x:y;
}
private:
T x,y;
};
int main()
{
Compare<int>com1(,); //用类模板定义对象com1,此时T被int替代
Compare<double>com2(12.34,56.78); //用类模板定义对象com2,此时T被double替代
Compare<char>com3('a','x'); //用类模板定义对象com3,此时T被char替代
cout<<"其中的最大值是:"<<com1.max()<<endl;
cout<<"其中的最大值是:"<<com2.max()<<endl;
cout<<"其中的最大值是:"<<com3.max()<<endl;
return ;
}
/*
程序运行结果是:
其中的最大值是:7
其中的最大值是:56.78
其中的最大值是:x
*/
在以上例子中,成员函数(其中含有类型参数)是定义类体内的。但是,类模板中的成员函数,也可以在类模板外定义。此时,若成员函数中有参数类型存在,则C++有一些特殊的规定:
(1)需要在成员函数定义之前进行模板声明;
(2)在成员函数名前缀上"类名<类型参数>::";
在类模板外定义成员函数的一般形式如下:
temlate<typename 类型参数>
函数类型 类名<类型参数>::成员函数名(形参表)
{
函数体;
} 如上题中成员函数max在类模板外定义时,应该写成:
template<typename T>
T Compare<T>::max()
{
return (x>y)?x:y;
}
//例6.7 在类模板外定义成员函数函数举例。
#include<iostream.h>
template<typename T> //模板声明,其中T为类型参数
class Compare{
public:
Compare(T i,T j)
{
x = i;
y = j;
}
T max();
private:
T x,y;
};
template<class T>
T Compare<T>::max()
{
return (x>y)?x:y;
}
int main()
{
Compare<int>com1(,); //用类模板定义对象com1,此时T被int替代
Compare<double>com2(12.34,56.78); //用类模板定义对象com2,此时T被double替代
Compare<char>com3('a','x'); //用类模板定义对象com3,此时T被char替代
cout<<"其中的最大值是:"<<com1.max()<<endl;
cout<<"其中的最大值是:"<<com2.max()<<endl;
cout<<"其中的最大值是:"<<com3.max()<<endl;
return ;
}
/*
程序运行结果是:
其中的最大值是:7
其中的最大值是:56.78
其中的最大值是:x 此例中,类模板Compare经实例化后生成了3个类型分别为int、double、char的模板类,这3个模板类
经实例化后又生成了3个对象com1、com2、com3。类模板代表了一类类,模板类表示某一具体的类。关系如下: 类模板
Compare<T>
实例化成模板类:Compare<int> Compare<double> Compare<char>
实例化模板类对象:com1 com2 com3
*/
//例6.8 类模板Stack的使用举例。
#include<iostream.h>
const int size=;
template<class T> //模板声明,其中T为类型参数
class Stack{ //类模板为Stack
public:
void init()
{
tos=;
}
void push(T ob); //声明成员函数push的原型,函数参数类型为T类型
T pop(); //声明成员函数pop的原型,其返回值类型为T类型
private:
T stack[size]; //数组类型为T,即是自可取任意类型
int tos;
};
template<class T> //模板声明
void Stack<T>::push(T ob) //在类模板体外定义成员函数push
{
if(tos==size)
{
cout<<"Stack is full"<<endl;
return;
}
stack[tos]=ob;
tos++;
}
template<typename T> //模板声明
T Stack<T>::pop() //在类模板体外定义成员函数push
{
if(tos==)
{
cout<<"Stack is empty"<<endl;
return ;
}
tos--;
return stack[tos];
}
int main()
{
//定义字符堆栈
Stack<char> s1; //用类模板定义对象s,此时T被char取代
s1.init();
s1.push('a');
s1.push('b');
s1.push('c');
for(int i=;i<;i++){cout<<"pop s1:"<<s1.pop()<<endl;} //定义整型堆栈
Stack<int> s2; //用类模板定义对象s,此时T被int取代
s2.init();
s2.push();
s2.push();
s2.push();
for(int i=;i<;i++){cout<<"pop s2:"<<s2.pop()<<endl;} return ;
} /*
程序运行结果是:
pop s1:c
pop s1:b
pop s1:a
pop s2:5
pop s2:3
pop s2:1 说明:
(1)在每一个类模板定义之前,都需要在前面加上模板声明,如
template<typename T>
或
tempplate<class T> 并且,类模板在使用时,必须在模板类名字后面缀上<类型参数> ,如
Stack<T> (2)如同模板函数一样,模板类也可以有多个类型参数。
*/
//例6.9 有两个类型参数的类模板举例
#include<iostream.h>
template<class QQ,class T> //声明模板,具有T1,T2两个类型参数
class Myclass{ //定义模板类Myclass
public:
Myclass(QQ a,T b);
void show();
private:
QQ x;
T y;
};
template<typename QQ,typename T>
Myclass<QQ,T>::Myclass(QQ a,T b)
{
x = a;
y = b;
}
template<class QQ,class T>
void Myclass<QQ,T>::show()
{
cout<<"x="<<x<<","<<"y="<<y<<endl;
}
int main()
{
Myclass <int,double>m1(,0.15); //用类模板定义对象m1,此时T1,T2分别被int、double取代
Myclass <int,char*>m2(,"This a test."); //用类模板定义对象m2,此时T1,T2分别被int,char*取代 m1.show();
m2.show(); return ;
}
/*
程序运行结果是:
x=12,y=0.15
x=12,y=This a test.
*/
C++:类模板与模板类的更多相关文章
- C++中模板类使用友元模板函数
在类模板中可以出现三种友元声明:(1)普通非模板类或函数的友元声明,将友元关系授予明确指定的类或函数.(2)类模板或函数模板的友元声明,授予对友元所有实例的访问权.(3)只授予对类模板或函数模板的特定 ...
- CI 模板解析器类
模板解析器类可以解析你的视图文件中的伪变量.它可以解析简单的变量或者以变量作为标签的结构.如果你以前没有用过模板引擎,那么伪变量如下所示: <html><head><ti ...
- 读书笔记 effective c++ Item 43 了解如何访问模板化基类中的名字
1. 问题的引入——派生类不会发现模板基类中的名字 假设我们需要写一个应用,使用它可以为不同的公司发送消息.消息可以以加密或者明文(未加密)的方式被发送.如果在编译阶段我们有足够的信息来确定哪个信息会 ...
- C++ 类模板与模板类详解
在C++的Template中很多地方都用到了typename与class这两个关键字,有时候这两者可以替换,那么这两个关键字是否完全一样呢? 事实上class用于定义类,在模板引入c++后,最初定义模 ...
- C++类模板和模板类
C++ 中有一个重要特性,那就是模板类型.类似于Objective-C中的泛型.C++通过类模板来实现泛型支持. 1 基础的类模板 类模板,可以定义相同的操作,拥有不同数据类型的成员属性. 通常使用t ...
- 如何导出标准模板库(STL)类的实例化和包含STL类对象数据成员的类
本文翻译自 https://support.microsoft.com/zh-cn/help/168958/how-to-export-an-instantiation-of-a-standard-t ...
- 《C++ Primer Plus》第16章 string类和标准模板库 学习笔记
C++提供了一组功能强大的库,这些库提供了很多常见编程问题的解决方案以及简化其他问题的工具string类为将字符串作为对象来处理提供了一种方便的方法.string类提供了自动内存管理动能以及众多处理字 ...
- C++ 类模板三(类模版中的static关键字)
//类模版中的static关键字 #include<iostream> using namespace std; /* 类模板本质上是c++编译器根据类型参数创建了不同的类, c++编译器 ...
- C++ 类模板一(类模板的定义)
//类模版语法 #include<iostream> using namespace std; /* 类模板和函数模板深入理解 1.编译器并不是把函数模板处理成能处理任何类型的函数 2.编 ...
随机推荐
- 小课堂Week10 例外处理设计的逆袭Part3
小课堂Week10 例外处理设计的逆袭Part3 今天是<例外处理设计的逆袭>这本书阅读的第三天,也是最后一天,我们会主要通过实例,对Part2中提出的例外处理等级进行解读. Level1 ...
- 提高Linux安全性--hosts.allow, hosts.deny 文件修改方法
有一种办法来提高Linux安全性--修改 hosts.allow , hosts.deny 这2个文件来配置 允许某个ip访问, 或者禁止访问. 可以通过这种方式设置限制 sshd 的远程访问, 只允 ...
- mac os去除去除.DS_Store文件--使用python和go(原创)
.DS_Store (英文全称 Desktop Services Store)是一种由苹果公司的Mac OS X操作系统所创造的隐藏文件,目的在于存贮文件夹的自定义属性,例如文件们的图标位置或者是背景 ...
- 基于WCF的API实现
本文程序基于VS2013.EF6.1.WCF WCF有2种方式,一是SOAP,一种是Restful 由于程序是基于PCL(可移植类库)的,所以不能用直接引入WCF服务的方式 网上的Restful方式的 ...
- macos port总结
http://stackoverflow.com/questions/733951/unable-to-download-the-source-code-of-open-source-projects ...
- Feature Stapling in SharePoint 2010
http://msdn.microsoft.com/en-us/library/bb861862(v=office.12).aspx http://gallery.technet.microsoft. ...
- Luence简单实现1
初步认识Luence,简单按照官方文档做了个例子,大牛绕开,仅供小白路过参考.如有错误,欢迎指正批评. 建一个简单工程,并且加入这几个小奶瓶,如下图: 注:版本不同,可能对jdk的需求是不同的,这个需 ...
- C#异常类总结
http://msdn.microsoft.com/zh-cn/library/aa664610(v=vs.71).aspx C#异常类相关总结 C#异常类一.基类Exception C#异常类二.常 ...
- 3243: [Noi2013]向量内积 - BZOJ
Description 两个d 维向量A=[a1,a2,...,ad]与B=[b1,b2,...,bd]的内积为其相对应维度的权值的乘积和,即: 现有 n 个d 维向量x1,...,xn ,小喵喵想知 ...
- 1231: [Usaco2008 Nov]mixup2 混乱的奶牛 - BZOJ
Description 混乱的奶牛 [Don Piele, 2007] Farmer John的N(4 <= N <= 16)头奶牛中的每一头都有一个唯一的编号S_i (1 <= S ...