1.函数模板
函数模板与模板函数的区别:函数模板和类模板如同具有各种形状的模板、模板函数和模板类则相当于按
照模板描绘,其形状相同,只是颜色各异。
软件工程知识:模板是C++软件可重用的重要功能之一。
测试和调试提示:函数模板和宏一样,支持软件的重用。但与宏不同的是,函数模板还可以消除许多类型
错误,因为C++提供了安全而全面的类型检查。
常见编程错误:函数模板的每个形式类型参数前不放置关键字class(或新的关键字typename)。
#include <iostream>
using namespace std;
template < class T >
void printArray( const T *array, const int count )
{
for ( int i = 0; i < count; i ++ )
cout << array[i] << " ";
cout << endl;
}
int main()
{
const int aCount = 5;
const int bCount = 6;
const int cCount = 7;
int a[ aCount ] = {1,2,3,4,5};
double b[ bCount ] = {1.1,2.2,3.3,4.4,5.5,6.6,7.7};
char c[ cCount ] = "Hello";
cout << "array a contains:" << endl;
printArray( a, aCount );
cout << "Array b contains:" << endl;
printArray( b, bCount );
cout << "Array c contains:" << endl;
printArray( c, cCount );
system("pause");
return 0;
}
本例中,由于采用了模板,程序员就不必用原型
void printArray( const int *, const int );
void printArray( const double *, const int );
void printArray( const char *, const int );
编写3个重载函数。除了类型T外,代码都相同。
性能提示:模板凸显了软件重用的好外。但记住,尽管模板只编写一次,但程序中仍须实例化多个模板函
数和模板类的副本。这些副本会占用大量的内存。
2.重载模板函数
常见编程错误:如果使用用户自定义类的类型调用模板,而模板对该类型对象使用==,+,<=等操作符,
那么这些操作符就需要重载。如果不重载这些操作符,就会发生错误,因为编译器在这些函数不存在的情
况下,仍然会调用这些重载的操作符函数。
常见编程错误:编译器通过匹配过程确定调用的函数,找不到匹配或找到多个匹配,就会出现编译错误。
3.类模板
软件工程知识:类模板通过实例化通用类的特定版本增强了软件的重用性。
/*头文件*/
#ifndef TSTACK_H
#define TSTACK_H
template < class T >
class stack
{
public:
Stack( );
~Stack()
{
delete[] StackPtr;
}
bool push( const T& );
bool pop( T& );
private:
int size;
int top;
T *stackPtr;
bool isEmpty() const
{
return top = -1;
}
bool isFull() const
{
return top = size - 1;
}
};
template < class T >
Stack< T >::Stack( int s )
{
size = s > 0 ? s : 10;
top = - 1;
stackPtr = new T[ size ];
}
template < class T >
bool Stack< T >::push( const T &pushValue )
{
if ( !isFull )
{
stackPtr[ ++ top ] = pushValue;
return true;
}
return false;
}
template < class T >
bool Stack< T >::pop( const T &popValue )
{
if ( !isEmpty )
{
popValue = stackPtr[ top -- ];
return true;
}
return false;
}
#endif
/*工程文件*/
#include <iostream>
#include "tstack.h"
using namespace std;
int main()
{
Stack< double >doubleStack( 5 );
double f -1.1;
cout << "pushing elements onto doubleStack/n";
while ( doubleStack.push( f ) )
{
cout << f << " ";
f += 1.1;
}
cout << "/nStack is full. cannot push" << f
<< "/n/npopping elements from doubleStack/n";
while ( doubleStack.pop( f ) )
{
cout << f << '';
}
cout << "/nStack is empty. Cannot push" ;
Stack< int > intStack;
int i = 1;
cout << "/npushing elements onto intStack/n";
while ( intStack.push( i ) )
{
cout << i << '';
++ i;
}
cout << "/nStack is full.Cannot push" << i
<< "/n/nPopping elements from intStack/n";
while ( intStack.pop( i ) )
{
cout << i << '';
}
cout << "/nintStack is Empty. Cannot pop/n";
return 0;
}
3.类模板与无类型参数
在类模板中Stack类模板只采用了模板首部的类型参数。它还可以使用无类型参数(non-type parameter),
可以有默认参数,一般作为常量处理。例如,模板首部可以取int elements参数,如下所示
template< class T, int elements >
然后声明
Stack< double, 100 >mostRecentSalesFigures;
在编译时实例化100个元素的Stack模板类mostRecentSalesFigures(使用double值)。这个模板类的类型为
Stack< double, 100>。类的首部可以包含private数据成员,数组声明如下
T StackHolder[elements];
性能提示:如果可能,应在编译时指定容器类(如数组类和堆栈类)的长度(可能通过非类型模板长度参数)
以消除new动态生成空间所引起的执行时开销。
性能提示:如果可能,应在编译时指定容器类的长度(可能通过非类型模板长度参数)以避免new元法取得
所需内存时引发致命的运行时错误。