转自:http://blog.youkuaiyun.com/csw_100/article/details/5844615
函数模板与类模板有什么区别?
答:函数模板的实例化是由编译程序在处理函数调用时自动完成的,而类模板的实例化必须由程序员在程序中显式地指定,即函数模板允许隐式调用和显式调用而类模板只能显示调用 。
这期间有涉及到函数模板与模板函数,类模板与模板类的概念 (类似于类与类对象的区别)
请看下面例子:
注意:模板类的函数声明和实现必须都在头文件中完成,不能像普通类那样声明在.h文件中实现在.cpp文件中,原因可以看链接http://blog.youkuaiyun.com/wangzengdi/article/details/28625627
当你不使用这个模版函数或模版类,编译器并不实例化它 ,当你使用时,编译器需要实例化它, 因为编译器是一次只能处理一个编译单元, 也就是一次处理一个cpp文件,所以实例化时需要看到该模板的完整定义 . 所以都放在头文件中 这不同于普通的函数, 在使用普通的函数时,编译时只需看到该函数的声明即可编译, 而在链接时由链接器来确定该函数的其实模板实现不能放在cpp文件中,主要就是CPP在c++编译期间不能决定模板参数的类型,所以不能生成模板函数的实例,所以他会把模板类型带到链接期间,如果这个期间有函数调用了该实例,这个时候由于没有把模板实例到特定类型,就会导致编译错误。
# include "stdafx.h"
# include < iostream >
using namespace std ;
//使用模板创建一个返回最大值的函数
//这是一个函数模板
template < class Type>
Type MaxValue( Type a, Type b)
{
if ( a > b)
{
return a;
}
else
return b;
}
//创建一个堆栈模板类
//这是一个类模板
template < class T>
class Stack
{
public :
Stack ( ) { m_nPos = 0; }
~ Stack ( ) { }
void Push( T value) ;
T Pop( ) ;
bool IsEmpty( )
{
return m_nPos = = 0;
}
bool HasElement( )
{
return ! IsEmpty( ) ;
}
bool IsFull( )
{
return m_nPos = = STATCK_SIZE;
}
private :
int m_nPos;
//使用常量表示堆栈的大小
const static int STATCK_SIZE = 100;
T m_Data[ STATCK_SIZE] ;
} ;
//模板类的成员函数实现
template < class T>
void Stack < T> : : Push( T value)
{
//使用后置递增操作符
m_Data[ m_nPos+ + ] = value;
}
template < class T>
T Stack < T> : : Pop( )
{
//使用前置递减操作符
return m_Data[ - - m_nPos] ;
}
void TestMaxValue( )
{
//1.隐式调用
// 函数模板的实例化在程序调用时自动完成
cout < < MaxValue( 100 , 204) < < endl ; //MaxValue( 100 , 204) 这是一个模板函数
cout < < MaxValue( 2. 5002, 30. 003) < < endl ; //MaxValue( 2. 5002, 30. 003)这也是一个模板函数
// 当然由程序员自己指定也可以
//2.显示调用
cout < < MaxValue< int > ( 10, 20) < < endl ;
cout < < MaxValue< double > ( 2. 5002, 30. 003) < < endl ;
}
void TestStack( )
{
//1.测试模板类(整数)
Stack < int > intStack; //类模板的实例化由程序员显示的指定
intStack. Push( 10) ;
intStack. Push( 20) ;
intStack. Push( 30) ;
while ( intStack. HasElement( ) )
{
cout < < intStack. Pop( ) < < endl ;
}
//2.测试模板类(浮点)
Stack < float > floatStack; //类模板的实例化由程序员显示的指定
floatStack. Push( 1. 001) ;
floatStack. Push( 2. 002) ;
floatStack. Push( 3. 003) ;
while ( floatStack. HasElement( ) )
{
cout < < floatStack. Pop( ) < < endl ;
}
//3.测试动态创建对象
//Stack创建的指针必须指明类型
Stack < int > * pInt = new Stack < int > ( ) ; 类模板的实例化由程序员显示的指定
pInt- > Push( 10);
pInt- > Push( 20) ;
pInt- > Push( 30) ;
while ( pInt- > HasElement( ) )
{
cout < < pInt- > Pop( ) < < endl ;
}
if ( pInt ! = NULL )
{
delete pInt;
pInt = NULL ;
}
}