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

📄 index.html

📁 C程序员手册(英文)
💻 HTML
📖 第 1 页 / 共 4 页
字号:
<tt>  short int u = 5, v = 10;</tt>
<tt>  short int w = min(u,v);</tt>
<tt>}</tt>
</pre>
<p>Still, the template version of <tt>min</tt> has a clear advantage over the 
  function: It can handle pointers and any other user-defined types. You want 
  the benefits of a template while avoiding the unnecessary generation of specializations. 
  How can these be avoided? A simple solution is to safely cast the arguments 
  into one common type before invoking the function template. For example:</p>
<pre>
<tt>void no_proliferation()</tt>
<tt>{</tt>
<tt>  short n = 5, m= 10;</tt>
<tt>  int j = min( static_cast&lt;int&gt; (n), </tt>
<tt>               static_cast&lt;int&gt; (m) ); //min&lt;int&gt; instantiated</tt>
<tt>  char c = 'a', d = 'b';</tt>
<tt>  char k = static_cast&lt;char&gt; (min( static_cast&lt;int&gt; , </tt>
<tt>                                   static_cast&lt;int&gt;  ) ); //min&lt;int&gt; used</tt>
<tt>}</tt>
</pre>
<p>This technique can also be applied to pointers: First, they have to be cast 
  to <tt>void<b> </b>*</tt>, and then they must be cast back to their original 
  type. When you are using pointers to polymorphic objects, pointers to derived 
  objects are cast to pointers to a base class.</p>
<p>For very small templates such as <tt>min</tt>, casting the arguments into a 
  common denominator type is not worth the trouble. Nonetheless, when nontrivial 
  templates that contain hundreds of code lines are used, you might consider doing 
  so.</p>
<h3> <a name="Heading19">Explicit Template Instantiation</a></h3>
<p>As was previously noted, templates are instantiated only if they are used in 
  the program. Generally, compilers generate the necessary code for a specialization 
  when they encounter its use in the source file. When large applications that 
  consist of hundreds of source files have to be compiled, this can cause a significant 
  increase in compilation time because the compiler's processing is repeatedly 
  interrupted when it has to generate code for sporadic specializations. The recurrent 
  interruption can occur in almost every source file because they use -- almost 
  without exception -- template classes of the Standard Library. Consider a simple 
  project that consists of only three source files:</p>
<pre>
<tt>//filename func1.cpp</tt>
<tt>#include &lt;string&gt;</tt>
<tt>#include &lt;iostream&gt;</tt>
<tt>using namespace std;</tt>
<tt>void func1()</tt>
<tt>{</tt>
<tt>  string s;  //generate default constructor and destructor</tt>
<tt>  s = "hello";  //generate assignment operator for const char *</tt>
<tt>  string s2;</tt>
<tt>  s2 = s;  // generate operator = const string&amp;, string&amp;</tt>
<tt>  cout&lt;&lt;s2.size(); // generate string::size, ostream&amp; operator &lt;&lt;(int)</tt>
<tt>}</tt>
<tt>//func1.cpp</tt>
<tt>//filename func2.cpp</tt>
<tt>#include &lt;string&gt;</tt>
<tt>#include &lt;iostream&gt;</tt>
<tt>using namespace std;</tt>
<tt>void func2()</tt>
<tt>{</tt>
<tt> string s;  //generate default constructor and destructor</tt>
<tt>cout&lt;&lt;"enter a string: "&lt;&lt;endl; //generate ostream&amp; operator&lt;&lt;(const char *)</tt>
<tt> cin&gt;&gt;s //generate istream&amp; operator&gt;&gt;(string&amp;)</tt>
<tt>}</tt>
<tt>//func2.cpp</tt>
<tt>//filename main.cpp</tt>
<tt>int main()</tt>
<tt>{</tt>
<tt>  func1();</tt>
<tt>  func2();</tt>
<tt>  retrun 0;</tt>
<tt>}</tt>
<tt>// main.cpp</tt>
</pre>
<p>The compilation time can be reduced if all the necessary template code is instantiated 
  all at once, thereby avoiding the repeated interruption of the compiler's processing. 
  For this purpose, you can use an <i>explicit instantiation</i>. An explicit 
  instantiation is indicated by the keyword <tt>template</tt> (without the <tt>&lt;&gt;</tt>), 
  followed by a template declaration.<b> </b>Here are a few examples of explicit 
  template instantiations:</p>
<pre>
<tt>template &lt;class T&gt; class A{/*..*/};</tt>
<tt>template&lt;class T&gt; void func(T&amp;) { }</tt>
<tt>  //filename instantiations.hpp</tt>
<tt>template class Vector&lt;short&gt;;  //explicit instantiation of a class template</tt>
<tt>template A&lt;int&gt;::A&lt;int&gt;(); //explicit instantiation of a member function</tt>
<tt>template class </tt>
<tt>  std::basic_string&lt;char&gt;; //explicit instantiation of a namespace member</tt>
<tt>template void func&lt;int&gt;(int&amp;); //explicit instantiation of a function template</tt>
</pre>
<h4> Examples of Explicit Instantiations in the Standard Library</h4>
<p>The Standard Library defines several specializations of class templates. One 
  example is the class template <tt>basic_string&lt;&gt;</tt>. Two specialized 
  versions of this class are <tt>std::string</tt> and <tt>std::wstring</tt>, which 
  are <tt>typedef</tt>s of the specializations <tt>basic_string&lt;char&gt;</tt> 
  and <tt>basic_string&lt;wchar_t&gt;</tt>, respectively. Usually, there is no 
  need to instantiate any of these explicitly because the header <tt>&lt;string&gt;</tt> 
  already instantiates these specializations:</p>
<pre>
<tt>#include &lt;string&gt; //definitions of std::string and std::wstring</tt>
<tt>using namespace std;</tt>
<tt>bool TranslateToKorean(const string&amp; origin, </tt>
<tt>                       wstring&amp; target ); //English / Korean dictionary</tt>
<tt>  int main()</tt>
<tt>  {</tt>
<tt>    string EnglishMsg = "This program has performed an illegal operation";</tt>
<tt>    wstring KoreanMsg;</tt>
<tt>    TranslateToKorean(EnglishMsg, KoreanMsg);</tt>
<tt>  }</tt>
</pre>
<h3> <a name="Heading20"> Exported Templates</a></h3>
<blockquote>
  <hr>
  <strong>NOTE: </strong> Exported templates are relatively new in C++; therefore, 
  not all compilers support this feature yet. Please consult your user's manual 
  to check whether your compiler supports it. 
  <hr>
</blockquote>
<p>A template definition can be <tt>#included</tt> in several translation units; 
  consequently, it can be compiled several times. As you have observed, this can 
  considerably increase compilation and linkage time. Instead of <tt>#including</tt> 
  a complete definition of the template, it is possible to compile the template 
  definition only once, and use only the template's declaration in other translation 
  units. This is very similar to the compilation of external functions and classes, 
  in which the definition is compiled only once and then only the declarations 
  are required.</p>
<p>To compile a template separately and then use its declaration, the template 
  has to be <i>exported</i>. This is done by preceding the template's definition 
  with the keyword <tt>export</tt>:</p>
<pre>
<tt>//filename min.cpp</tt>
<tt>export template &lt; class T &gt; T min (const T&amp; a, const T&amp; b)</tt>
<tt>{</tt>
<tt>  return a &gt; b ? b : a;</tt>
<tt>}</tt>
</pre>
<p>Now only the declaration of the template is required when it is used in other 
  translation units. For example</p>
<pre>
<tt>  //file min.c</tt>
<tt>template &lt; class T &gt; T min (const T &amp; a, const T &amp; b); //declaration only</tt>
<tt>int main()</tt>
<tt>{</tt>
<tt>  int j=0, k=1;</tt>
<tt>  in smaller = min(j,k);</tt>
<tt>  return 0;</tt>
<tt>}</tt>
</pre>
<p>Inline function templates cannot be exported. If an inline template function 
  is declared both <tt>export</tt> and <tt>inline</tt>, the <tt>export</tt> declaration 
  has no effect and the template is only inline. Declaring a class template exported 
  is equivalent to declaring all its non-inline member functions, static data 
  members, and member classes exported. Templates in an unnamed namespace are 
  not to be exported.</p>
<h2> <a name="Heading21">Interaction with Other Language Features</a></h2>
<p>The interaction of templates with other language features can sometimes yield 
  surprising results. The following sections discuss various aspects of interaction 
  between templates and other language features, including ambiguous interpretation 
  of qualified template names, inheritance, and virtual member functions.</p>
<h3> <a name="Heading22">The typename Keyword</a></h3>
<p>Using qualified names in a template can cause ambiguity between a type and 
  a non-type. For example</p>
<pre>
<tt>int N;</tt>
<tt>template &lt; class T &gt; T func()</tt>
<tt>{</tt>
<tt>  T::A * N;  // ambiguous: multiplication  or a pointer declaration?</tt>
<tt>//</tt>
<tt>}</tt>
</pre>
<p> If <tt>T::A</tt> is a typename, the definition of <tt>func() N</tt> creates 
  a pointer. If, on the other hand, <tt>T::A</tt> is a non-type (for example, 
  if <tt>A</tt> is data member of type <tt>int</tt>), <tt>T::A * N</tt> is an 
  expression statement that consists of the multiplication of the qualified member 
  <tt>T::A</tt> by a global <tt>int N</tt>. By default, the compiler assumes that 
  an expression such as <tt>T::A</tt> refers to a non-type. The <tt>typename</tt> 
  keyword instructs the compiler to supersede this default interpretation and 
  resolve the ambiguity in favor of a type name rather than a non-type. In other 
  words, the preceding (seemingly ambiguous) statement is actually resolved as 
  a multiplication expression, the result of which is discarded. In order to declare 
  a pointer, the <tt>typename</tt> keyword is required:</p>
<pre>
<tt>int N;</tt>
<tt>template &lt; class T &gt; T func()</tt>
<tt>{</tt>
<tt>  typename T::A * N; // N is a now pointer since T::A is a typename</tt>
<tt>//...</tt>
<tt>};</tt>
</pre>
<h3> <a name="Heading23">Inheritance Relationship of Templates</a></h3>
<p>A common mistake is to assume that a container of pointers or references to 
  objects of a derived class is a container of pointers or references to a base 
  class. For example</p>
<pre>
<tt>#include&lt;vector&gt;</tt>
<tt>using namespace std;</tt>
<tt>class Base</tt>
<tt>{</tt>
<tt>public: virtual void f() {}</tt>
<tt>};</tt>
<tt>class Derived : public Base</tt>
<tt>{</tt>
<tt>public: void f() {}</tt>
<tt>};</tt>
<tt>void func( vector&lt;Base*&gt;&amp; vb);</tt>
<tt>int main()</tt>
<tt>{</tt>
<tt>  Derived d;</tt>
<tt>  vector&lt;Derived*&gt; vd;</tt>
<tt>  vd.push_back(&amp;d);</tt>
<tt>  func(vd); //error, vector&lt;Derived*&gt;&amp; is not a vector&lt;Base*&gt;</tt>
<tt>}</tt>
</pre>
<p>Although the is-a relationship exists between the classes <tt>Derived</tt> 
  and <tt>Base</tt>, there is no such relationship between specializations of 
  the same class template that contain pointers or references to related objects.</p>
<h3> <a name="Heading24">Virtual Member Functions</a></h3>
<p>A member function template should not be virtual. However, ordinary member 
  functions in a class template <i>can</i> be virtual. For example</p>
<pre>
<tt>template &lt;class T&gt; class A</tt>
<tt>{</tt>
<tt>public:</tt>
<tt>  template &lt;class S&gt; virtual void f(S);   //error</tt>
<tt>  virtual int g(); // OK</tt>
<tt>};</tt>
</pre>
<p>A specialization of a member function template does not override a virtual 
  function that is defined in a base class. For example</p>
<pre>
<tt>class Base</tt>
<tt>{</tt>
<tt>public:</tt>
<tt>  virtual void f(char);</tt>
<tt>};</tt>
<tt>class Derived : public Base</tt>
<tt>{</tt>
<tt>public:</tt>
<tt>  template &lt;class T&gt; void f(T);   //does not override  B::f(int)</tt>
<tt>};</tt>
</pre>
<h3> <a name="Heading25">Pointers to Members of a Class Template</a></h3>
<p>Pointers to class members can take the address of a specialized member function 
  of a class template. As with ordinary classes, pointers to members cannot take 
  the address of a static member function. In the following example, the specialization 
  <tt>std::vector&lt;int&gt;</tt> is used:</p>
<pre>
<tt>#include&lt;vector&gt;</tt>
<tt>using namespace std;</tt>
<tt>  // a typedef is used to hide the unwieldy syntax</tt>
<tt>typedef void (vector&lt; int &gt;::*pmv) (size_t);</tt>
<tt>void func()</tt>
<tt>{</tt>
<tt>  pmv  reserve_ptr = &amp;vector&lt; int &gt;::reserve;</tt>
<tt>  //...use reserve_ptr</tt>
<tt>}</tt>
</pre>
<h2> <a name="Heading26">Conclusions</a></h2>
<p>Templates simplify and streamline the implementation of generic containers 
  and functions. The benefits of templates have allured software vendors, who 
  are now migrating from plain object-oriented frameworks to object-oriented generic 
  frameworks. However, parameterized types are not unique to C++. Back in 1983, 
  Ada introduced generic packages, which were roughly equivalent to class templates. 
  Other languages implemented similar mechanisms of automated code generation 
  from a skeletal user-written code.</p>
<p>The two main template categories in C++ are class templates and function templates. 
  A class template encapsulates parameterized data members and function members. 
  Function templates are a means of implementing generic algorithms. The traditional 
  methods of implementing generic algorithms in pre-template C++ were rather limited, 
  unsafe, and inefficient compared to templates. An important aspect of templates 
  is the support of object semantics.</p>
<p>C++ enables programmers to control the instantiation of templates by explicitly 
  instantiating them. It is possible to instantiate an entire class, a certain 
  member function of a class, or a particular specialization of a function template. 
  An explicit instantiation of a template is indicated by the keyword <tt>template</tt>, 
  without angular brackets that are followed by the template declaration. Explicit 
  specializations of a class template are always required. For function templates, 
  the compiler usually deduces the specialization from the type of the arguments. 
  It is possible to define partial specialization of a class template that overrides 
  the primary class template for a set of types. This feature is most useful for 
  modifying the behavior of a class template that manipulates pointers. A partial 
  specialization is indicated by a secondary list of parameters following the 
  name of the template. An explicit specialization enables the programmer to override 
  the automatic instantiation of a class template for a certain type. An explicit 
  specialization is indicated by the keyword <tt>template</tt>, followed by empty 
  angular brackets and a list of type arguments after the template's name.</p>
<p>Templates and operator overloading are the building blocks of generic programming. 
  The Standard Template Library is an exemplary framework of generic programming, 
  as you will see in the next chapter.</p>
<CENTER>
<P>
<HR>
  <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> <BR>
<BR>
<BR>
<p></P>

<P>&#169; <A HREF="/publishers/que/series/professional/0789720221/copy.htm">Copyright 1999</A>, Macmillan Computer Publishing. All
rights reserved.</p>
</CENTER>


</BODY>

</HTML>

⌨️ 快捷键说明

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