📄 tut5-1.html
字号:
<P>
<CENTER>
<TABLE WIDTH=100% CELLPADDING=5 CELLSPACING=5><TR><TD BGCOLOR="#FFFFBF" WIDTH=50% VALIGN="top">
<TT><PRE><I>// class templates</I>
#include <iostream.h>
template <class T>
class pair {
T value1, value2;
public:
pair (T first, T second)
{value1=first; value2=second;}
T getmax ();
};
template <class T>
T pair<T>::getmax ()
{
T retval;
retval = value1>value2? value1 : value2;
return retval;
}
int main () {
pair <int> myobject (100, 75);
cout << myobject.getmax();
return 0;
}
</PRE></TT>
</TD><TD BGCOLOR="silver" WIDTH=50% VALIGN="top"><TT>
<B>100</B>
</TT></TD></TR></TABLE>
</CENTER>
notice how the definition of member function <TT><B>getmax</B></TT> begins:
<BLOCKQUOTE><TT>
template <class <B>T</B>><BR>
<B>T</B> pair<<B>T</B>>::getmax ()
</TT></BLOCKQUOTE>
All <TT><B>T</B></TT>s that appear are necessary because whenever you declare
member functions you have to follow a format similar to this (the second
<TT><B>T</B></TT> makes reference to the type returned by the function, so this may vary).
<P>
<H2>Template specialization</H2>
A template specialization allows a template to make specific implementations when
the pattern is of a determined type. For example, suppose that our class template
<TT><B>pair</B></TT> included a function to return the result of the module operation
between the objects contained in it, but we only want it to work when the contained
type is <TT><B>int</B></TT>.
For the rest of the types we want this function to return <TT><B>0</B></TT>.
This can be done the following way:
<P>
<CENTER>
<TABLE WIDTH=100% CELLPADDING=5 CELLSPACING=5><TR><TD BGCOLOR="#FFFFBF" WIDTH=50% VALIGN="top">
<TT><PRE><I>// Template specialization </I>
#include <iostream.h>
template <class T>
class pair {
T value1, value2;
public:
pair (T first, T second)
{value1=first; value2=second;}
T module () {return 0;}
};
template <>
class pair <int> {
int value1, value2;
public:
pair (int first, int second)
{value1=first; value2=second;}
int module ();
};
template <>
int pair<int>::module() {
return value1%value2;
}
int main () {
pair <int> myints (100,75);
pair <float> myfloats (100.0,75.0);
cout << myints.module() << '\n';
cout << myfloats.module() << '\n';
return 0;
}
</PRE></TT>
</TD><TD BGCOLOR="silver" WIDTH=50% VALIGN="top"><TT>
<B>25<BR>0</B>
</TT></TD></TR></TABLE>
</CENTER>
<P>
As you can see in the code the specialization is defined this way:
<BLOCKQUOTE><TT>
<B>template <> class </B><I>class_name</I><B> <</B><I>type</I><B>></B>
</TT></BLOCKQUOTE>
The specialization is part of a template, for that reason we must begin the declaration
with <TT><B>template <></B></TT>. And indeed because it is a specialization for a
concrete type, the generic type cannot be used in it and the first angle-brackets
<TT><B><></B></TT>
must appear empty. After the class name we must include the type that is being specialized
enclosed between angle-brackets <TT><B><></B></TT>.
<P>
When we specialize a type of a template we must also define all the members
equating them to the specialization (if one pays attention, in the example
above we have had to include its own constructor, although it is identical to the one
in the generic template). The reason is that no member is "inherited" from the generic
template to the specialized one.
<P>
<H2>Parameter values for templates</H2>
Besides the template arguments preceded by the <TT><B>class</B></TT> or <TT><B>typename</B></TT>
keywords that represent a type, function templates and class templates can include other
parameters that are not types whenever they are also constant values, like for example
values of fundamental types.
As an example see this class template that serves to store arrays:
<P>
<CENTER>
<TABLE WIDTH=100% CELLPADDING=5 CELLSPACING=5><TR><TD BGCOLOR="#FFFFBF" WIDTH=50% VALIGN="top">
<TT><PRE><I>// array template</I>
#include <iostream.h>
template <class T, int N>
class array {
T memblock [N];
public:
void setmember (int x, T value);
T getmember (int x);
};
template <class T, int N>
array<T,N>::setmember (int x, T value) {
memblock[x]=value;
}
template <class T, int N>
T array<T,N>::getmember (int x) {
return memblock[x];
}
int main () {
array <int,5> myints;
array <float,5> myfloats;
myints.setmember (0,100);
myfloats.setmember (3,3.1416);
cout << myints.getmember(0) << '\n';
cout << myfloats.getmember(3) << '\n';
return 0;
}
</PRE></TT>
</TD><TD BGCOLOR="silver" WIDTH=50% VALIGN="top"><TT>
<B>100<BR>3.1416</B>
</TT></TD></TR></TABLE>
</CENTER>
<P>
It is also possible to set default values for any template parameter just as it
is done with function parameters.
<P>
Some possible template examples seen above:
<BLOCKQUOTE><TT><PRE>
template <class T> // The most usual: one class parameter.
template <class T, class U> // Two class parameters.
template <class T, int N> // A class and an integer.
template <class T = char> // With a default value.
template <int Tfunc (int)> // A function as parameter.
</TT></BLOCKQUOTE>
<P>
<H2>Templates and multiple-file projects</H2>
From the point of view of the compiler, templates are not normal functions or classes.
They are compiled on demand, meaning that the code of a template function is not
compiled until an instantiation is required. At that moment, when an instantiation is
required, the compiler generates a function specifically for that type from the template.
<P>
When projects grow it is usual to split the code of a program in different source files.
In these cases, generally the interface and implementation are separated.
Taking a library of functions as example, the interface generally consists of the
prototypes of all the functions that can be called. These are generally declared in a
"header file" with <TT><B>.h</B></TT> extension, and the implementation (the definition
of these functions) is in an independent file of c++ code.
<P>
The macro-like functionality of templates, forces a restriction for multi-file
projects: the implementation (definition) of a template class or function <U>must</U> be
in the same file as the declaration. That means we cannot separate the interface in a
separate header file and we must include both interface and implementation in any file
that uses the templates.
<P>
Going back to the library of functions, if we wanted to make a library of function templates,
instead of creating a header file (<TT><B>.h</B></TT>) we should create a "template file"
with both the interface and implementation of the function templates
(there is no convention on the extension for this type of file other than there be no extension at all or to keep the .h).
The inclusion more
than once of the same template file with both declarations and definitions in a project
doesn't generate linkage errors, since they are compiled on demand and compilers that allow
templates should be prepared to not generate duplicate code in these cases.
<!--cuatut-->
<P>
<CENTER><TABLE WIDTH=100% CELLPADDING=0 CELLSPACING=0 BORDER=0>
<TR><TD BGCOLOR="#0000FF"><IMG SRC="head0.gif" WIDTH=2 HEIGHT=2></TD></TR>
<TR><TD ALIGN="right"><FONT FACE="arial,helvetica" SIZE=1>© The C++ Resources Network, 2000-2003 - All rights reserved</FONT></TD></TR>
</TABLE></CENTER>
<P>
<CENTER>
<TABLE CELLPADDING=0 WIDTH=100%>
<TR><TD ALIGN="right" WIDTH=45%><A HREF="tut4-4.html">
<IMG SRC="butnback.gif" ALIGN="right" BORDER=0>
Previous:<BR><B>4-4. Polymorphism.</B></A></TD>
<TD ALIGN="center" WIDTH=10%><A HREF="index.html">
<IMG SRC="butnindx.gif" BORDER=0><BR>
index</A></TD>
<TD ALIGN="left" WIDTH=45%><A HREF="tut5-2.html">
<IMG SRC="butnnext.gif" ALIGN="left" BORDER=0>
Next:<BR><B>5-2. Namespaces.</B></A>
</TD></TR></TABLE>
</CENTER>
<!--/cuatut-->
</BODY>
</HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -