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.编 ...
随机推荐
- hibernate数据库配置
在文件夹etc中 ## MySQL #hibernate.dialect org.hibernate.dialect.MySQLDialect #hibernate.dialect org.hiber ...
- ASP.NET中的母版页机制
项目中用到了母版页,由于好长时间没用了,不太熟悉起原理,在网上找了一下: http://www.cnblogs.com/_zjl/archive/2011/06/12/2078992.html 有时间 ...
- 感知器算法PLA
for batch&supervised binary classfication,g≈f <=> Eout(g)≥0 achieved through Eout(g)≈Ein(g ...
- LAMP开发之环境搭建(2014.12.7在ubuntu下)
Ubuntu下搭建LAMP环境 前言:学习PHP脚本编程语言之前,必须先搭建并熟悉开发环境,开发环境有很多种,例如LAMP.WAMP.MAMP等.这里我搭建的是LAMP环境,即Linux.Apache ...
- 连续子数组的最大和/1007. Maximum Subsequence Sum (25)
题目描述 HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学.今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决.但是,如果向量 ...
- awk中文手册
1. 前言 有关本手册 : 这是一本awk学习指引, 其重点着重于 : l awk 适于解决哪些问题 ? l awk 常见的解题模式为何 ? 为使读者快速掌握awk解题的模 ...
- Mininet安装及使用
最简单的方法是开始 下载一个预包装Mininet / Ubuntu VM . 这个虚拟机包括Mininet本身,所有预装OpenFlow二进制文件和工具,调整内核配置,以支持更大的Mininet网络. ...
- 【Timers】win服务 定时器
win服务: using System.ServiceProcess; 继承 ServiceBase 即可 定时器: private System.Timers.Timer PushOrderTime ...
- C#之多态
多态是面向对象编程中三大机制之一,其原理建立在"从父类继承而来的子类可以转换为其父类"这个规则之上,换句话说,能用父类的地方,就能用该类的子类.当从父类派生了很多子类时,由于每个子 ...
- D2GS1.11 的DC Key的相關設置指南
D2GS1.11版本暗黑戰網服務器DC Key 的相關設置是保存在 D2Server.ini 文件中的.在這裡我列舉跟DC Key 有關的配置條款. (以下內容具存在於D2Server.ini 文件中 ...