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

📄 ch09.htm

📁 c++语言操作手册
💻 HTM
📖 第 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. Allrights reserved.</p></CENTER></BODY></HTML>

⌨️ 快捷键说明

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