📄 tut5-1.html
字号:
<HTML>
<HEAD>
<TITLE>C++ Tutorial: 5.1, Templates</TITLE>
<META NAME="description" CONTENT="Function Templates. Class Templates. Specialization. Value parameters.">
<META NAME="keywords" CONTENT="template typename">
</HEAD>
<BODY BGCOLOR="white">
<!--captut-->
<CENTER>
<TABLE WIDTH=100% CELLPADDING=0 CELLSPACING=1 BORDER=0>
<TR><TD WIDTH=90%>
<FONT SIZE=4> Section 5.1 </FONT><BR>
<FONT SIZE=5><B>Templates</B></FONT>
</TD><TD><!--ad--><!--#include virtual="/ad/ad468.shtml"--><!--/ad-->
</TD><TD VALIGN="bottom"><A HREF="http://www.cplusplus.com/doc/tutorial/">
<IMG SRC="head.gif" ALT="cplusplus.com" BORDER=0></A></TD></TR>
<TR><TD BGCOLOR="#0000FF" ALIGN="center" COLSPAN=3>
<IMG SRC="head0.gif" WIDTH=2 HEIGHT=2 BORDER=0></TD></TR>
</TABLE>
</CENTER>
<!--/captut-->
<P>
<TABLE><TR><TD BGCOLOR="#BFFFBF">
<IMG SRC="icoansi.gif" ALIGN="left">
Templates are a new feature introduced by ANSI-C++ standard. If
you use a C++ compiler that is not adapted to this standard it is possible
that you cannot use them.<BR>
</TD></TR></TABLE>
<P>
<H2>Function templates</H2>
Templates allow to create generic functions that admit any data type as parameters
and return a value without having to overload the function with all the possible data types.
Until certain point they fulfill the functionality of a macro. Its prototype is any
of the two following ones:
<BLOCKQUOTE><TT>
<B>template <class </B><I>identifier</I><B>></B> <I>function_declaration</I>;<BR>
<B>template <typename </B><I>identifier</I><B>></B> <I>function_declaration</I>;<BR>
</TT></BLOCKQUOTE>
the only difference between both prototypes is the use of keyword <TT><B>class</B></TT>
or <TT><B>typename</B></TT>, its use is indistinct since both expressions have exactly
the same meaning and behave exactly the same way.
<P>
For example, to create a template function that returns the greater one of two objects
we could use:
<BLOCKQUOTE><TT><PRE>
template <class GenericType>
GenericType GetMax (GenericType a, GenericType b) {
return (a>b?a:b);
}
</PRE></TT></BLOCKQUOTE>
As the first line specifies, we have created a template for a generic data type that we
have called <TT><B>GenericType</B></TT>. Therefore in the function that follows,
<TT><B>GenericType</B></TT> becomes a valid data type and it is used
as the type for its two parameters <TT><B>a</B></TT> and <TT><B>b</B></TT> and as the return type
for the function <TT><B>GetMax</B></TT>.
<P>
<TT><B>GenericType</B></TT> still does not represent any concrete data type;
when the function <TT><B>GetMax</B></TT> will be called we will be able
to call it with any valid data type. This data type will serve as a <I>pattern</I> and
will replace <TT><B>GenericType</B></TT> in the function.
The way to call a template class with a type pattern is the following:
<BLOCKQUOTE><TT>
<I>function</I> <B><</B><I>pattern</I><B>> (</B><I>parameters</I><B>);</B>
</TT></BLOCKQUOTE>
Thus, for example, to call <TT><B>GetMax</B></TT> and to compare two integer values
of type <TT><B>int</B></TT> we can write:
<BLOCKQUOTE><TT>
int x,y;<BR>
GetMax <int> (x,y);
</TT></BLOCKQUOTE>
so <TT><B>GetMax</B></TT> will be called as if each appearance of
<TT><B>GenericType</B></TT> was replaced by an <TT><B>int</B></TT> expression.
<P>
Here is the complete example:
<P>
<CENTER>
<TABLE WIDTH=100% CELLPADDING=5 CELLSPACING=5><TR><TD BGCOLOR="#FFFFBF" WIDTH=50% VALIGN="top">
<TT><PRE><I>// function template</I>
#include <iostream.h>
template <class T>
T GetMax (T a, T b) {
T result;
result = (a>b)? a : b;
return (result);
}
int main () {
int i=5, j=6, k;
long l=10, m=5, n;
k=GetMax<int>(i,j);
n=GetMax<long>(l,m);
cout << k << endl;
cout << n << endl;
return 0;
}
</PRE></TT>
</TD><TD BGCOLOR="silver" WIDTH=50% VALIGN="top"><TT>
<B>6<BR>10</B>
</TT></TD></TR></TABLE>
</CENTER>
<P>
(In this case we have called the generic type <TT><B>T</B></TT> instead of
<TT><B>GenericType</B></TT> because it is shorter and in addition is one of the most
usual identifiers used for templates, although it is valid to use any valid identifier).
<P>
In the example above we used the same function <TT><B>GetMax()</B></TT> with arguments
of type <TT><B>int</B></TT> and <TT><B>long</B></TT> having written a single implementation
of the function. That is to say, we have written a function template and called it
with two different patterns.
<P>
As you can see, within our <TT><B>GetMax()</B></TT> template function
the type <TT><B>T</B></TT> can be used to declare new objects:
<BLOCKQUOTE><TT>T result;</TT></BLOCKQUOTE>
<TT><B>result</B></TT> is an object of type <TT><B>T</B></TT>, like
<TT><B>a</B></TT> and <TT><B>b</B></TT>, that is to say, of the type that we enclose
between angle-brackets <TT><></TT> when calling our template function.
<P>
In this concrete case where the generic <TT><B>T</B></TT> type is used as a parameter for
function <TT><B>GetMax</B></TT> the compiler can find out automatically which data type
is passed to it without having to specify it with patterns <TT><B><int></B></TT>
or <TT><B><long></B></TT>. So we could have written:
<BLOCKQUOTE><TT>
int i,j;<BR>
GetMax (i,j);
</TT></BLOCKQUOTE>
since both <TT><B>i</B></TT> and <TT><B>j</B></TT> are of type <TT><B>int</B></TT>
the compiler would assume automatically that the wished function is for type
<TT><B>int</B></TT>. This implicit method is more usual and would produce the same result:
<P>
<CENTER>
<TABLE WIDTH=100% CELLPADDING=5 CELLSPACING=5><TR><TD BGCOLOR="#FFFFBF" WIDTH=50% VALIGN="top">
<TT><PRE><I>// function template II</I>
#include <iostream.h>
template <class T>
T GetMax (T a, T b) {
return (a>b?a:b);
}
int main () {
int i=5, j=6, k;
long l=10, m=5, n;
k=GetMax(i,j);
n=GetMax(l,m);
cout << k << endl;
cout << n << endl;
return 0;
}
</PRE></TT>
</TD><TD BGCOLOR="silver" WIDTH=50% VALIGN="top"><TT>
<B>6<BR>10</B>
</TT></TD></TR></TABLE>
</CENTER>
<P>
Notice how in this case, within function <TT><B>main()</B></TT> we called our template
function <TT><B>GetMax()</B></TT> without explicitly specifying the type between
angle-brackets <TT><B><></B></TT>. The compiler automatically determines what type
is needed on each call.
<P>
Because our template function includes only one data type (<TT><B>class T</B></TT>) and both
arguments it admits are both of that same type, we cannot call our template function
with two objects of different types as parameters:
<BLOCKQUOTE><TT><FONT COLOR="red">
int i;<BR>
long l;<BR>
k = GetMax (i,l);
</FONT></TT></BLOCKQUOTE>
This would be incorrect, since our function waits for two arguments of <U>the same</U> type
(or class).
<P>
We can also make template-functions that admit more than one generic class or
data type. For example:
<BLOCKQUOTE><TT><PRE>
template <class T, class U>
T GetMin (T a, U b) {
return (a<b?a:b);
}
</PRE></TT></BLOCKQUOTE>
In this case, our template function <TT><B>GetMin()</B></TT> admits two parameters of
different types and returns an object of the same type as the first parameter
(<TT><B>T</B></TT>) that is passed. For example, after that declaration we could call
the function by writing:
<BLOCKQUOTE><TT><PRE>
int i,j;
long l;
i = GetMin<int,long> (j,l);
</PRE></TT></BLOCKQUOTE>
or simply
<BLOCKQUOTE><TT><PRE>
i = GetMin (j,l);
</PRE></TT></BLOCKQUOTE>
even though <TT><B>j</B></TT> and <TT><B>l</B></TT> are of different types.
<P>
<H2>Class templates</H2>
We also have the possibility to write class templates, so that a class can have members
based on generic types that do not need to be defined at the moment of creating the class
or whose members use these generic types. For example:
<BLOCKQUOTE><TT><PRE>
template <class T>
class pair {
T values [2];
public:
pair (T first, T second)
{
values[0]=first; values[1]=second;
}
};
</PRE></TT></BLOCKQUOTE>
The class that we have just defined serves to store two elements of any valid type.
For example, if we wanted to declare an object of this class to store two integer values
of type <TT><B>int</B></TT> with the values
<TT><B>115</B></TT> and <TT><B>36</B></TT> we would write:
<BLOCKQUOTE><TT>
pair<int> myobject (115, 36);
</TT></BLOCKQUOTE>
this same class would also serve to create an object to store any other type:
<BLOCKQUOTE><TT>
pair<float> myfloats (3.0, 2.18);
</TT></BLOCKQUOTE>
The only member function has been defined <I>inline</I> within the class declaration. If
we define a function member outside the declaration
we must always precede the definition with the prefix <TT><B>template <... ></B></TT>.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -