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

📄 appendixb.html

📁 《C++编程思想》中文版。。。。。。。。。。。。。
💻 HTML
📖 第 1 页 / 共 3 页
字号:
object, which occurs when passing by value. Normally you don’t want to be
worrying too much about efficiency issues when designing and building your
system, but this habit is a sure
win.</FONT><LI><FONT FACE="Verdana">	</FONT><FONT FACE="Georgia">Be aware of
temporaries<B>.</B> When tuning for performance, watch out for temporary
creation, especially with operator overloading. If your constructors and
destructors are complicated, the cost of creating and destroying temporaries can
be high. When returning a value from a function, always try to build the object
&#8220;in place&#8221; with a constructor call in the return statement:
</FONT><BR><TT><FONT FACE="Courier New"><B>return MyType(i,
j);</B></FONT></TT><BR><FONT FACE="Georgia">rather
than</FONT><BR><TT><FONT FACE="Courier New"><B>MyType x(i,
j);</B></FONT></TT><BR><TT><FONT FACE="Courier New"><B>return
x;</B></FONT></TT><BR><FONT FACE="Georgia">The former return statement (the
so-called <I>return-value optimization</I>)<I> </I>eliminates a copy-constructor
call and destructor
call.</FONT><LI><FONT FACE="Verdana">	</FONT><FONT FACE="Georgia">When creating
constructors, consider exceptions. In the best case, the constructor won&#8217;t
do anything that throws an exception. In the next-best scenario, the class will
be composed and inherited from robust classes only, so they will automatically
clean themselves up if an exception is thrown. If you must have naked pointers,
you are responsible for catching your own exceptions and then deallocating any
resources pointed to before you throw an exception in your constructor. If a
constructor must fail, the appropriate action is to throw an
exception.</FONT><LI><FONT FACE="Verdana">	</FONT><FONT FACE="Georgia">Do only
what is minimally necessary in your constructors. Not only does this produce a
lower overhead for constructor calls (many of which may not be under your
control) but your constructors are then less likely to throw exceptions or cause
problems.</FONT><LI><FONT FACE="Verdana">	</FONT><FONT FACE="Georgia">The
responsibility of the destructor is to release resources allocated during the
lifetime of the object, not just during
construction.</FONT><LI><FONT FACE="Verdana">	</FONT><FONT FACE="Georgia">Use
exception hierarchies, preferably derived from the Standard C++ exception
hierarchy and nested as public classes within the class that throws the
exceptions. The person catching the exceptions can then catch the specific types
of exceptions, followed by the base type. If you add new derived exceptions,
existing client code will still catch the exception through the base
type.</FONT><LI><FONT FACE="Verdana">	</FONT><FONT FACE="Georgia">Throw
exceptions by value and catch exceptions by reference. Let the
exception-handling mechanism handle memory management. If you throw pointers to
exception objects that have been created on the heap, the catcher must know to
destroy the exception, which is bad coupling. If you catch exceptions by value,
you cause extra constructions and destructions; worse, the derived portions of
your exception objects may be sliced during upcasting by
value.</FONT><LI><FONT FACE="Verdana">	</FONT><FONT FACE="Georgia">Don&#8217;t
write your own class templates unless you must. Look first in the Standard C++
Library, then to vendors who create special-purpose tools. Become proficient
with their use and you&#8217;ll greatly increase your
productivity.</FONT><LI><FONT FACE="Verdana">	</FONT><FONT FACE="Georgia">When
creating templates, watch for code that does not depend on type and put that
code in a non-template base class to prevent needless code bloat. Using
inheritance or composition, you can create templates in which the bulk of the
code they contain is type-dependent and therefore
essential.</FONT><LI><FONT FACE="Verdana">	</FONT><FONT FACE="Georgia">Don&#8217;t
use the <B>&lt;cstdio&gt;</B> functions, such as <B>printf(&#160;)</B>. Learn to
use iostreams instead; they are type-safe and type-extensible, and significantly
more powerful. Your investment will be rewarded regularly. In general, always
use C++ libraries in preference to C
libraries.</FONT><LI><FONT FACE="Verdana">	</FONT><FONT FACE="Georgia">Avoid
C&#8217;s built-in types. They are supported in C++ for backward compatibility,
but they are much less robust than C++ classes, so your bug-hunting time will
increase.</FONT><LI><FONT FACE="Verdana">	</FONT><FONT FACE="Georgia">Whenever
you use built-in types as globals or automatics, don&#8217;t define them until
you can also initialize them. Define variables one per line along with their
initialization. When defining pointers, put the &#8216;<B>*</B>&#8217; next to
the type name. You can safely do this if you define one variable per line. This
style tends to be less confusing for the
reader.</FONT><LI><FONT FACE="Verdana">	</FONT><FONT FACE="Georgia">Guarantee
that initialization occurs in all aspects of your code. Perform all member
initialization in the constructor initializer list, even built-in types (using
pseudo-constructor calls). Using the constructor initializer list is often more
efficient when initializing subobjects; otherwise the default constructor is
called, and you end up calling other member functions (probably
<B>operator=</B>) on top of that in order to get the initialization you
want.</FONT><LI><FONT FACE="Verdana">	</FONT><FONT FACE="Georgia">Don&#8217;t
use the form <B>MyType a = b;</B> to define an object. This one feature is a
major source of confusion because it calls a constructor instead of the
<B>operator=</B>. For clarity, always be specific and use the form <B>MyType
a(b);</B> instead. The results are identical, but other programmers won&#8217;t
be confused.</FONT><LI><FONT FACE="Verdana">	</FONT><FONT FACE="Georgia">Use the
explicit casts described in Chapter 3. A cast overrides the normal typing system
and is a potential error spot. Since the explicit casts divide C&#8217;s
one-cast-does-all into classes of well-marked casts, anyone debugging and
maintaining the code can easily find all the places where logical errors are
most likely to
happen.</FONT><LI><FONT FACE="Verdana">	</FONT><FONT FACE="Georgia">For a
program to be robust, each component must be robust. Use all the tools provided
by C++: access control, exceptions, const-correctness, type checking, and so on
in each class you create. That way you can safely move to the next level of
abstraction when building your
system.</FONT><LI><FONT FACE="Verdana">	</FONT><FONT FACE="Georgia">Build in
<B>const</B>-correctness. This allows the compiler to point out bugs that would
otherwise be subtle and difficult to find. This practice takes a little
discipline and must be used consistently throughout your classes, but it pays
off.</FONT><LI><FONT FACE="Verdana">	</FONT><FONT FACE="Georgia">Use compiler
error checking to your advantage. Perform all compiles with full warnings, and
fix your code to remove all warnings. Write code that utilizes the compile-time
errors and warnings rather than that which causes runtime errors (for example,
don&#8217;t use variadic argument lists, which disable all type checking). Use
<B>assert(&#160;)</B> for debugging, but use exceptions for runtime
errors.</FONT><LI><FONT FACE="Verdana">	</FONT><FONT FACE="Georgia">Prefer
compile-time errors to runtime errors. Try to handle an error as close to the
point of its occurrence as possible. Prefer dealing with the error at that point
to throwing an exception. Catch any exceptions in the nearest handler that has
enough information to deal with them. Do what you can with the exception at the
current level; if that doesn&#8217;t solve the problem, rethrow the exception.
(See Volume 2 for more
details.)</FONT><LI><FONT FACE="Verdana">	</FONT><FONT FACE="Georgia">If
you&#8217;re using exception specifications (see Volume 2 of this book,
downloadable from <I>www.BruceEckel.com</I>, to learn about exception handling),
install your own <B>unexpected(&#160;)</B> function using
<B>set_unexpected(&#160;)</B>. Your <B>unexpected(&#160;)</B> should log the
error and rethrow the current exception. That way, if an existing function gets
overridden and starts throwing exceptions, you will have a record of the culprit
and can modify your calling code to handle the exception.
</FONT><LI><FONT FACE="Verdana">	</FONT><FONT FACE="Georgia">Create a
user-defined <B>terminate(&#160;)</B> (indicating a programmer error) to log the
error that caused the exception, then release system resources, and exit the
program.</FONT><LI><FONT FACE="Verdana">	</FONT><FONT FACE="Georgia">If a
destructor calls any functions, those functions might throw exceptions. A
destructor cannot throw an exception (this can result in a call to
<B>terminate(&#160;)</B>, which indicates a programming error), so any
destructor that calls functions must catch and manage its own
exceptions.</FONT><LI><FONT FACE="Verdana">	</FONT><FONT FACE="Georgia">Don&#8217;t
create your own &#8220;decorated&#8221; private data member names (prepending
underscores, Hungarian notation, etc.), unless you have a lot of pre-existing
global values; otherwise, let classes and namespaces do the name scoping for
you.</FONT><LI><FONT FACE="Verdana">	</FONT><FONT FACE="Georgia">Watch for
overloading. A function should not conditionally execute code based on the value
of an argument, default or not. In this case, you should create two or more
overloaded functions
instead.</FONT><LI><FONT FACE="Verdana">	</FONT><FONT FACE="Georgia">Hide your
pointers inside container classes. Bring them out only when you are going to
immediately perform operations on them. Pointers have always been a major source
of bugs. When you use <B>new</B>, try to drop the resulting pointer into a
container.<B> </B>Prefer that a container &#8220;own&#8221; its pointers so
it&#8217;s responsible for cleanup. Even better, wrap a pointer inside a class;
if you still want it to look like a pointer, overload <B>operator-&gt; </B>and
<B>operator*</B>.<B> </B>If you must have a free-standing pointer, always
initialize it, preferably to an object address, but to zero if necessary. Set it
to zero when you delete it to prevent accidental multiple
deletions.</FONT><LI><FONT FACE="Verdana">	</FONT><FONT FACE="Georgia">Don&#8217;t
overload global <B>new</B> and <B>delete</B>; always do this on a class-by-class
basis. Overloading the global versions affects the entire client programmer
project, something only the creators of a project should control. When
overloading <B>new</B> and <B>delete</B> for classes, don&#8217;t assume that
you know the size of the object; someone may be inheriting from you. Use the
provided argument. If you do anything special, consider the effect it could have
on
inheritors.</FONT><LI><FONT FACE="Verdana">	</FONT><FONT FACE="Georgia">Prevent
object slicing. It virtually never makes sense to upcast an object by value. To
prevent upcasting by value, put pure virtual functions in your base
class.</FONT><LI><FONT FACE="Verdana">	</FONT><FONT FACE="Georgia">Sometimes
simple aggregation does the job. A &#8220;passenger comfort system&#8221; on an
airline consists of disconnected elements: seat, air conditioning, video, etc.,
and yet you need to create many of these in a plane. Do you make private members
and build a whole new interface? No &#8211; in this case, the components are
also part of the public interface, so you should create public member objects.
Those objects have their own private implementations, which are still safe. Be
aware that simple aggregation is not a solution to be used often, but it does
happen. </FONT><A NAME="_Toc312374168"></A></OL><FONT FACE = "Verdana"><H1 ALIGN="LEFT">
</H1></FONT>





<HR><DIV ALIGN="LEFT"><P><A NAME="fn65" HREF="#fnB65">[65]</A><FONT FACE="Georgia" SIZE=2>
Explained to me by Andrew Koenig.</FONT><BR></P></DIV>

<DIV ALIGN="CENTER">
    <FONT FACE="Verdana" size = "-1">
     [ <a href="AppendixA.html">Previous Chapter</a> ] 
    [ <a href="Contents.html">Table of Contents</a> ] 
    [ <a href="DocIndex.html">Index</a> ]
     [ <a href="AppendixC.html">Next Chapter</a> ] 
    </FONT>
    <BR>
 Last Update:09/27/2001</P></DIV>

</BODY>

</HTML>

⌨️ 快捷键说明

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