⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 index.html

📁 C程序员手册(英文)
💻 HTML
📖 第 1 页 / 共 4 页
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>

<HEAD>
	<META NAME="Author" Content="Steph Mineart">
	<META HTTP-EQUIV="Content-Type" CONTENT="text/html;CHARSET=iso-8859-1">
	<TITLE>ANSI/ISO C++ Professional Programmer's Handbook - Chapter 9 - Templates</TITLE>
	<link rel="stylesheet"  TYPE="text/css" href="/includes/stylesheets/ebooks.css">
</head>

<BODY TEXT="#000000" BGCOLOR="#FFFFFF">

<CENTER>
<H1><img src="/publishers/que/series/professional/0789720221/button/que.gif" WIDTH="171" HEIGHT="66" ALIGN="BOTTOM" BORDER="0"><BR>
ANSI/ISO C++ Professional Programmer's Handbook</H1>
</CENTER>
<CENTER>
  <P><A HREF="/publishers/que/series/professional/0789720221/index.htm"><img src="/publishers/que/series/professional/0789720221/button/contents.gif" WIDTH="128"
HEIGHT="28" ALIGN="BOTTOM" ALT="Contents" BORDER="0"></A> 
  <HR>
</CENTER>
<H1 align="center">9</H1>
<h1 align="center"> Templates</h1>
<address>by Danny Kalev</address>
<ul>
  <li><a href="#Heading1">Introduction</a> 
  <li><a href="#Heading2">Class Templates</a> 
    <ul>
      <li><a href="#Heading3">Declaration of a Class Template</a> 
      <li><a href="#Heading4">Instantiation and Specialization</a> 
      <li><a href="#Heading5">Template Arguments</a> 
      <li><a href="#Heading6">Default Type Arguments</a> 
      <li><a href="#Heading7">Static Data Members</a> 
      <li><a href="#Heading8">Friendship</a> 
      <li><a href="#Heading9">Partial Specialization</a> 
      <li><a href="#Heading10">Explicit Specialization of a Class Template</a> 
      <li><a href="#Heading11">Specializations of Class Template Functions</a> 
    </ul>
  <li><a href="#Heading12">Function Templates</a> 
    <ul>
      <li><a href="#Heading13">Function-Like Macros</a> 
      <li><a href="#Heading14">void Pointers</a> 
      <li><a href="#Heading15">A Common Root Base</a> 
    </ul>
  <li><a href="#Heading16">Performance Considerations</a> 
    <ul>
      <li><a href="#Heading17">Type Equivalence</a> 
      <li><a href="#Heading18">Avoiding Unnecessary Instantiations</a> 
      <li><a href="#Heading19">Explicit Template Instantiation</a> 
      <li><a href="#Heading20"> Exported Templates</a> 
    </ul>
  <li><a href="#Heading21">Interaction with Other Language Features</a> 
    <ul>
      <li><a href="#Heading22">The typename Keyword</a> 
      <li><a href="#Heading23">Inheritance Relationship of Templates</a> 
      <li><a href="#Heading24">Virtual Member Functions</a> 
      <li><a href="#Heading25">Pointers to Members of a Class Template</a> 
    </ul>
  <li><a href="#Heading26">Conclusions</a> 
</ul>
<hr size=4>
<h2><a name="Heading1">Introduction</a></h2>
<p>A <i>template</i> is a mold from which the compiler generates a family of classes 
  or functions. C++ programming styles and concepts have changed considerably 
  since the first implementation of templates back in 1991 (in <tt>cfront</tt> 
  2.0). Initially, templates were viewed as a support for generic container classes 
  such as <tt>Array</tt> and <tt>List</tt>. In recent years, the experience of 
  using templates has shown that this feature is most useful in designing and 
  implementing general-purpose libraries such as the Standard Template Library. 
  Templatized libraries and frameworks are both efficient and portable. With the 
  widespread usage of templates, C++ has added more sophisticated constructs to 
  control their behavior and performance, including partial specializations, explicit 
  specializations, template members, exported templates, default type arguments, 
  and more.</p>
<p>This chapter discusses various aspects of designing and implementing templates. 
  First, class templates are explained. Function templates come next. Finally, 
  template issues of special concern -- such as pointers to members, virtual member 
  functions within a template class, inheritance relations, and explicit instantiations 
  -- are discussed.</p>
<h2> <a name="Heading2">Class Templates</a></h2>
<p>Many algorithms and data structures can be defined independently of the concrete 
  data type that they manipulate. Often, the reliance on a hardwired data type 
  is merely a programming artifact. The concept of a complex number, for instance, 
  is not exclusively limited to the fundamental type <tt>double</tt>. Rather, 
  it is applicable to every floating-point type. Designing a type-independent 
  class that abstracts the concept of a complex number has many advantages because 
  it enables users to choose the desired level of precision for a specific application 
  without having to reduplicate code manually. In addition, type-independent classes 
  are more portable among different platforms and locales.</p>
<h3> <a name="Heading3">Declaration of a Class Template</a></h3>
<p>A class template is declared using the keyword <tt>template</tt>, followed 
  by a <i>template parameter list</i> that is enclosed in angular brackets and 
  a declaration or a definition of the class. For example</p>
<pre>
<tt>template &lt;class T&gt; class Vector; //declaration</tt>
<tt>template &lt;class T&gt; class Vector  //definition</tt>
<tt>{</tt>
<tt>private:</tt>
<tt>  size_t sz;</tt>
<tt>  T * buff;</tt>
<tt>public:</tt>
<tt>  explicit Vector&lt;T&gt;(size_t s = 100);</tt>
<tt>  Vector&lt;T&gt; (const Vector &lt;T&gt; &amp; v); //copy constructor</tt>
<tt>  Vector&lt;T&gt;&amp; operator= (const Vector&lt;T&gt;&amp; v); //assignment operator</tt>
<tt>  ~Vector&lt;T&gt;(); //destrcutor</tt>
<tt>  //other member functions</tt>
<tt>  T&amp; operator [] (unsigned int index);</tt>
<tt>  const T&amp; operator [] (unsigned int index) const;</tt>
<tt>  size_t size() const;</tt>
<tt>}; </tt>
</pre>
<p>Member functions of a class template can be defined outside the class body. 
  In this case, they have to be explicitly declared as member functions of their 
  class template. For example</p>
<pre>
<tt>//definitions of Vector's member functions</tt>
<tt>//follow the class declaration</tt>
<tt>template &lt;class T&gt; Vector&lt;T&gt;::Vector&lt;T&gt; (size_t s) //constructor definition</tt>
<tt>: sz(s),</tt>
<tt>buff (new T[s])</tt>
<tt>{}</tt>
<tt>template &lt;class T&gt; Vector&lt;T&gt;::Vector&lt;T&gt; (const Vector &lt;T&gt; &amp; v) //copy ctor</tt>
<tt>{</tt>
<tt>  sz = 0;</tt>
<tt>  buff = 0; </tt>
<tt>  *this = v; //use overloaded assignment operator</tt>
<tt>}</tt>
<tt>template &lt;class T&gt; Vector&lt;T&gt;&amp; Vector&lt;T&gt;::operator=   // assignment operator</tt>
<tt>(const Vector &lt;T&gt; &amp; v)</tt>
<tt>{</tt>
<tt>  if (this == &amp;v)</tt>
<tt>    return *this;</tt>
<tt>  this-&gt;Vector&lt;T&gt;::~Vector&lt;T&gt;(); //call destructor </tt>
<tt>  buff = new T[v.size()]; //allocate sufficient storage</tt>
<tt>  for (size_t i =0; i &lt; v.size(); i++)</tt>
<tt>    buff[i] = v[i]; //memberwise copy</tt>
<tt>  sz = v.size();</tt>
<tt>  return *this;</tt>
<tt>}</tt>
<tt>template &lt;class T&gt; Vector&lt;T&gt;::~Vector&lt;T&gt; () //destructor</tt>
<tt>{</tt>
<tt>  delete [] buff;</tt>
<tt>}</tt>
<tt>template &lt;class T&gt; inline T&amp; Vector&lt;T&gt;::operator [] (unsigned int i)</tt>
<tt>{</tt>
<tt>  return buff[i];</tt>
<tt>}</tt>
<tt>template &lt;class T&gt; inline const T&amp; Vector&lt;T&gt;::operator [] //const version</tt>
<tt>(unsigned int i) const</tt>
<tt>{</tt>
<tt>  return buff[i];</tt>
<tt>}</tt>
<tt>template &lt;class T&gt; inline size_t Vector&lt;T&gt;::size () const</tt>
<tt>{</tt>
<tt>  return sz;</tt>
<tt>}</tt>
<tt>//Vector.hpp</tt>
</pre>
<p>The prefix <tt>template &lt;class T&gt;</tt> indicates that <tt>T</tt> is a 
  <i>template parameter</i>, which is a placeholder for a yet unspecified type. 
  The keyword <tt>class</tt> is of particular interest because the corresponding 
  argument for the parameter <tt>T</tt> is not necessarily a user-defined type; 
  it can also be a fundamental type, such as <tt>char</tt> or <tt>int</tt>. If 
  you prefer a more neutral term, you can use the <tt>typename</tt> keyword instead 
  (<tt>typename</tt> also has other uses, though, as you will see next):</p>
<pre>
<tt>template &lt;<b>typename</b> T&gt; class Vector //typename instead of class</tt>
<tt>                               //no semantic difference between the two forms</tt>
<tt>{</tt>
<tt>  //...</tt>
<tt>};</tt>
<tt>template &lt;<b>typename</b> T&gt; Vector&lt;T&gt;::Vector&lt;T&gt; (size_t s)</tt>
<tt>: sz(s), buff (new T[s]) {}</tt>
</pre>
<p>Within the scope of <tt>Vector</tt>, qualification with the parameter <tt>T</tt> 
  is redundant, so the member functions can be declared and defined without it. 
  The constructor, for example, can be declared as follows:</p>
<pre>
<tt>template &lt;class T&gt; class Vector</tt>
<tt>{</tt>
<tt>public:</tt>
<tt> Vector (size_t s = 100);  // equivalent to Vector &lt;T&gt;(size_t s = 100);</tt>
<tt>};</tt>
</pre>
<p>Similarly, the constructor's definition can omit the redundant parameter:</p>
<pre>
<tt>// equivalent to template &lt;class T&gt; Vector&lt;T&gt;::Vector&lt;T&gt;(size_t s)</tt>
<tt>template &lt;class T&gt; Vector&lt;T&gt;::Vector (size_t s) :</tt>
<tt>buff (new T[s]), sz(s)</tt>
<tt>{}</tt>
</pre>
<h3> <a name="Heading4">Instantiation and Specialization</a></h3>
<p>A class template is not a class. The process of instantiating a class from 
  a class template and a type argument is called <i>template instantiation</i>. 
  A <i>template id</i>, that is, a template<i> </i>name followed by a list of 
  arguments in angular brackets (for example, <tt>Vector&lt;int&gt;</tt>), is 
  called a <i>specialization</i>. A specialization of a class template can be 
  used exactly like any other class. Consider the following examples:</p>
<pre>
<tt>void func (Vector &lt;float&gt; &amp;); //function parameter</tt>
<tt>size_t n = sizeof( Vector &lt;char&gt;); //sizeof expression</tt>
<tt>class myStringVector: private Vector&lt;std::string&gt; //base class</tt>
<tt>{/*...*/};</tt>
<tt>#include &lt;iostream&gt;</tt>
<tt>#include &lt;typeinfo&gt;</tt>
<tt>#include &lt;string&gt;</tt>
<tt>using namespace std;</tt>
<tt>cout&lt;&lt;typeid(Vector&lt; string&gt;).name(); //typeid expression</tt>
<tt>Vector&lt;int&gt; vi; // creating an object</tt>
</pre>
<p>The compiler instantiates only the necessary member functions of a given specialization. 
  In the following example, points of member instantiation are numbered:</p>
<pre>
<tt>#include &lt;iostream&gt;</tt>
<tt>#include "Vector.hpp"</tt>
<tt>using namespace std;</tt>
<tt>int main()</tt>
<tt>{</tt>
<tt>  Vector&lt;int&gt; vi(5);  // 1</tt>
<tt>  for (int i = 0; i&lt;5; i++)</tt>
<tt>  {</tt>
<tt>    vi[i] = i; //fill vi   // 2</tt>
<tt>    cout&lt;&lt;vi[i]&lt;&lt;endl;</tt>
<tt>  }</tt>
<tt>  return 0;  // 3</tt>
<tt>}</tt>
</pre>
<p>The compiler generates code only for the following <tt>Vector</tt> member functions, 
  which are used either explicitly or implicitly in the program:</p>
<pre>
<tt>Vector&lt;int&gt;::Vector&lt;int&gt; (size_t s) //1: constructor</tt>
<tt>: sz(s), buff (new int[s]) {}</tt>
<tt>inline int&amp; Vector&lt;int&gt;::operator [] (unsigned int idx) //2: operator []</tt>
<tt>{</tt>
<tt>  return buff[idx];</tt>
<tt>}</tt>
<tt>Vector&lt;int&gt;::~Vector&lt;int&gt; () //3: destructor</tt>
<tt>{</tt>
<tt>  delete [] buff;</tt>
<tt>}</tt>
</pre>
<p>In contrast, code for the member function <tt>size_t Vector&lt;int&gt;::size() 
  const</tt> is not generated by the compiler because it is not required. For 
  some compilers, it might be simpler to instantiate all the class members at 
  once whether they are needed or not. However, the "generate on demand" policy 
  is a Standard requirement, and has two functions:</p>
<ul>
  <li>
    <p> <b>Efficiency</b> -- It is not uncommon for certain class templates to 
      define hundreds of member functions (STL containers, for example); normally, 
      however, fewer than a dozen of these are actually used in a program. Generating 
      the code for unused member functions times the number of specializations 
      used in the program can easily bloat the size of the executable -- and it 
      might unnecessarily increase compilation and linkage time.</p>
  </li>
  <p></p>
  <li>
    <p> <b>Flexibility</b> -- In some cases, not every type supports all the operations 
      that are defined in a class template. For example, a container class can 
      use <tt>ostream</tt>'s operator <tt>&lt;&lt;</tt> to display members of 
      fundamental types such as <tt>char</tt> and <tt>int</tt> and user-defined 
      types for which an overloaded version of <tt>&lt;&lt;</tt> is defined. However, 
      a POD (plain old data) struct for which no overloaded version of <tt>&lt;&lt;</tt> 
      exists can still be stored in such a container as long as the <tt>&lt;&lt;</tt> 
      is not invoked.</p>
  </li>
</ul>
<p></p>
<h3> <a name="Heading5">Template Arguments</a></h3>
<p>A template can take type parameters, that is, symbols that represent an as 
  yet unspecified type. For example</p>
<pre>
<tt>template &lt;class T &gt; class Vector {/*...*/};</tt>
</pre>
<p>A template can also take ordinary types such as <tt>int</tt> and <tt>long</tt> 
  as parameters:</p>
<pre>
<tt>template &lt;class T, int n&gt; class Array</tt>
<tt>{</tt>
<tt>private:</tt>
<tt>  T a[n];</tt>
<tt>  int size;</tt>
<tt>public:</tt>
<tt>  Array() : size (n){}</tt>
<tt>  T&amp; operator [] (int idx) { return a[idx]; }</tt>
<tt>};</tt>
</pre>
<p>Note, however, that when an ordinary type is used as a parameter, the template 
  argument must be a constant or a constant expression of an integral type. For 
  example</p>
<pre>
<tt>void  array_user()</tt>
<tt>{</tt>
<tt>  const int cn = 5;</tt>
<tt>  int num = 10;</tt>
<tt>  Array&lt;char, 5&gt; ac;  // OK, 5 is a const</tt>
<tt>  Array&lt;float, cn&gt; af;  // OK, cn is const</tt>
<tt>  Array&lt;unsigned char, sizeof(float)&gt; auc;  // OK, constant expression used</tt>
<tt>  Array&lt;bool,  num&gt; ab;  // error, num is not a constant</tt>
<tt>}</tt>
</pre>
<p>Besides constant expressions, other arguments that are allowed are a non-overloaded 
  pointer to member and the address of an object or a function with external linkage. 
  This also implies that a string literal cannot be used as a template argument 
  because it has internal linkage. For example:</p>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -