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

📄 mi32.htm

📁 一个非常适合初学者入门的有关c++的文档
💻 HTM
📖 第 1 页 / 共 2 页
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Frameset//EN" "http://www.w3.org/TR/REC-html40/frameset.dtd">
<HTML LANG="EN">
<HEAD>
<TITLE>More Effective C++ | Item 32: Program in the future tense</TITLE>
<LINK REL=STYLESHEET HREF=../INTRO/ECMEC.CSS>

<SCRIPT LANGUAGE="Javascript" SRC="../JAVA/COOKIE.JS"></SCRIPT>
<SCRIPT LANGUAGE="Javascript">var imagemax = 0; setCurrentMax(0);</SCRIPT>
<SCRIPT LANGUAGE="Javascript" SRC="../JAVA/DINGBATS.JS"></SCRIPT>
<SCRIPT LANGUAGE="Javascript">
var dingbase = "MI32_DIR.HTM";
var dingtext = "Item M32, P";
if (self == top) {
 top.location.replace(dingbase + this.location.hash);
}
</SCRIPT>

</HEAD>
<BODY BGCOLOR="#FFFFFF" TEXT="#000000" ONLOAD="setResize()">
<!-- SectionName="M32: Program in the future tense" -->
<A NAME="5373"></A>
<DIV ALIGN="CENTER"><FONT SIZE="-1">Back to <A HREF="./MMISC_FR.HTM" TARGET="_top">Miscellany</A> &nbsp;&nbsp;<BR>&nbsp;&nbsp;Continue to <A HREF="./MI33_FR.HTM" TARGET="_top">Item 33: Make non-leaf classes abstract</A></FONT></DIV>


<P><A NAME="dingp1"></A><font ID="mititle">Item 32: &nbsp;Program in the future tense.</font><SCRIPT>create_link(1);</SCRIPT>
</P>

<A NAME="72187"></A><A NAME="42180"></A>
<P><A NAME="dingp2"></A>
Things <NOBR>change.<SCRIPT>create_link(2);</SCRIPT>
</NOBR></P><A NAME="45982"></A>
<P><A NAME="dingp3"></A>
As software developers, we may not know much, but we do know that things will change. We don't necessarily know what will change, how the changes will be brought about, when the changes will occur, or why they will take place, but we do know this: things will <NOBR>change.<SCRIPT>create_link(3);</SCRIPT>
</NOBR></P><A NAME="45996"></A>
<P><A NAME="dingp4"></A>
Good software adapts well to change. It accommodates new features, it ports to new platforms, it adjusts to new demands, it handles new inputs. Software this flexible, this robust, and this reliable does not come about by accident. It is designed and implemented by programmers who conform to the constraints of today while keeping in mind the probable needs of tomorrow. This kind of software &#151; software that <A NAME="p253"></A>accepts change gracefully &#151; is written by people who <I>program in the future tense</I>.<SCRIPT>create_link(4);</SCRIPT>
</P><A NAME="46010"></A>
<P><A NAME="dingp5"></A>
To program in the future tense is to accept that things will change and to be prepared for it. It is to recognize that new functions will be added to libraries, that new overloadings will occur, and to watch for the potentially ambiguous function calls that might result (see <a href="../EC/EI26_FR.HTM#6337" TARGET="_top">Item E26</A>). It is to acknowledge that new classes will be added to hierarchies, that present-day derived classes may be tomorrow's base classes, and to prepare for that possibility. It is to accept that new applications will be written, that functions will be called in new contexts, and to write those functions so they continue to perform correctly. It is to remember that the programmers charged with software maintenance are typically not the code's original developers, hence to design and implement in a fashion that facilitates comprehension, modification, and enhancement by <NOBR>others.<SCRIPT>create_link(5);</SCRIPT>
</NOBR></P><A NAME="85839"></A>
<P><A NAME="dingp6"></A>
One way to do this is to express design constraints in C++ instead of (or in addition to) comments or other documentation. For example, if a class is designed to never have derived classes, don't just put a comment in the header file above the class, use C++ to prevent derivation; <a href="./MI26_FR.HTM#5350" TARGET="_top">Item 26</A> shows you how. If a class requires that all instances be on the heap, don't just tell clients that, enforce the restriction by applying the approach of <a href="./MI27_FR.HTM#22627" TARGET="_top">Item 27</A>. If copying and assignment make no sense for a class, prevent those operations by declaring the copy constructor and the assignment operator private (see <a href="../EC/EI27_FR.HTM#6406" TARGET="_top">Item E27</A>). C++ offers great power, flexibility, and expressiveness. Use these characteristics of the language to enforce the design decisions in your <NOBR>programs.<SCRIPT>create_link(6);</SCRIPT>
</NOBR></P><A NAME="46075"></A>
<P><A NAME="dingp7"></A>
Given that things will change, write classes that can withstand the rough-and-tumble world of software evolution. Avoid "demand-paged" virtual functions, whereby you make no functions virtual unless somebody comes along and demands that you do it. Instead, determine the <i>meaning</i> of a function and whether it makes sense to let it be redefined in derived classes. If it does, declare it virtual, even if nobody redefines it right away. If it doesn't, declare it nonvirtual, and don't change it later just because it would be convenient for someone; make sure the change makes sense in the context of the entire class and the abstraction it represents (see <a href="../EC/EI36_FR.HTM#7007" TARGET="_top">Item E36</A>).<SCRIPT>create_link(7);</SCRIPT>
</P><A NAME="46080"></A>
<P><A NAME="dingp8"></A>
Handle assignment and copy construction in every class, even if "nobody ever does those things." Just because they don't do them now doesn't mean they won't do them in the future (see <a href="../EC/EI18_FR.HTM#17774" TARGET="_top">Item E18</A>). If these functions are difficult to implement, declare them <CODE>private</CODE> (see <a href="../EC/EI27_FR.HTM#6406" TARGET="_top">Item E27</A>). That way no one will inadvertently call compiler-generated functions that do the wrong thing (as often happens with default assignment operators and copy constructors &#151; see <a href="../EC/EI11_FR.HTM#2042" TARGET="_top">Item E11</A>).<SCRIPT>create_link(8);</SCRIPT>
</P><A NAME="46094"></A>
<A NAME="p254"></A><P><A NAME="dingp9"></A>
Adhere to the principle of least astonishment: strive to provide classes whose operators and functions have a natural syntax and an intuitive semantics. Preserve consistency with the behavior of the built-in types: when in doubt, do as the <CODE>int</CODE>s <NOBR>do.<SCRIPT>create_link(9);</SCRIPT>
</NOBR></P><A NAME="46098"></A>
<P><A NAME="dingp10"></A>
Recognize that anything somebody <I>can</I> do, they <I>will</I> do. They'll throw exceptions, they'll assign objects to themselves, they'll use objects before giving them values, they'll give objects values and never use them, they'll give them huge values, they'll give them tiny values, they'll give them null values. In general, if it will compile, somebody will do it. As a result, make your classes easy to use correctly and hard to use incorrectly. Accept that clients will make mistakes, and design your classes so you can prevent, detect, or correct such errors (see, for example, <a href="./MI33_FR.HTM#10947" TARGET="_top">Item 33</A> and <a href="../EC/EI46_FR.HTM#195225" TARGET="_top">Item E46</A>).<SCRIPT>create_link(10);</SCRIPT>
</P><A NAME="46316"></A>
<P><A NAME="dingp11"></A>
Strive for portable code. It's not much harder to write portable programs than to write unportable ones, and only rarely will the difference in performance be significant enough to justify unportable constructs (see <a href="./MI16_FR.HTM#40995" TARGET="_top">Item 16</A>). Even programs designed for custom hardware often end up being ported, because stock hardware generally achieves an equivalent level of performance within a few years. Writing portable code allows you to switch platforms easily, to enlarge your client base, and to brag about supporting open systems. It also makes it easier to recover if you bet wrong in the operating system <NOBR>sweepstakes.<SCRIPT>create_link(11);</SCRIPT>
</NOBR></P><A NAME="46114"></A>
<P><A NAME="dingp12"></A>
Design your code so that when changes are necessary, the impact is localized. Encapsulate as much as you can; make implementation details private (e.g., <a href="../EC/EI20_FR.HTM#5976" TARGET="_top">Item E20</A>). Where applicable, use unnamed namespaces or file-<CODE>static</CODE> objects and functions (see <a href="./MI31_FR.HTM#34883" TARGET="_top">Item 31</A>). Try to avoid designs that lead to virtual base classes, because such classes must be initialized by every class derived from them &#151; even those derived indirectly (see <a href="./MI4_FR.HTM#5218" TARGET="_top">Item 4</A> and <a href="../EC/EI43_FR.HTM#7778" TARGET="_top">Item E43</A>). Avoid RTTI-based designs that make use of cascading <CODE>if</CODE>-<CODE>then</CODE>-<CODE>else</CODE> statements (see <a href="./MI31_FR.HTM#34883" TARGET="_top">Item 31</A> again, then see <a href="../EC/EI39_FR.HTM#7269" TARGET="_top">Item E39</A> for good measure). Every time the class hierarchy changes, each set of statements must be updated, and if you forget one, you'll receive no warning from your <NOBR>compilers.<SCRIPT>create_link(12);</SCRIPT>
</NOBR></P><A NAME="46140"></A>
<P><A NAME="dingp13"></A>
These are well known and oft-repeated exhortations, but most programmers are still stuck in the present tense. As are many authors, unfortunately. Consider this advice by a well-regarded C++ <NOBR>expert:<SCRIPT>create_link(13);</SCRIPT>
</NOBR></P><A NAME="46141"></A>
<A NAME="dingp14"></A><BLOCKQUOTE>You need a virtual destructor whenever someone deletes a <CODE>B*</CODE> that actually points to a <CODE>D</CODE>.<SCRIPT>create_link(14);</SCRIPT>
</BLOCKQUOTE>
<A NAME="46142"></A>
<P><A NAME="dingp15"></A>
Here <CODE>B</CODE> is a base class and <CODE>D</CODE> is a derived class. In other words, this author suggests that if your program looks like this, you don't need a virtual destructor in <CODE>B</CODE>:<SCRIPT>create_link(15);</SCRIPT>
</P>

<A NAME="46143"></A>
<UL><PRE><A NAME="p255"></A>
class B { ... };                   // no virtual dtor needed
class D: public B { ... };
<A NAME="46147"></A>
B *pb = new D;
</PRE>
</UL>

<A NAME="46148"></A>
<P><A NAME="dingp16"></A>
However, the situation changes if you add this <NOBR>statement:<SCRIPT>create_link(16);</SCRIPT>
</NOBR></P>

<A NAME="46149"></A>
<UL><PRE>
delete pb;                        // NOW you need the virtual
                                  // destructor in B
</PRE>
</UL>
<A NAME="46150"></A>
<P><A NAME="dingp17"></A>
The implication is that a minor change to client code &#151; the addition of a <CODE>delete</CODE> statement &#151; can result in the need to change the class definition for <CODE>B</CODE>. When that happens, all <CODE>B</CODE>'s clients must recompile. Following this author's advice, then, the addition of a single statement in one function can lead to extensive code recompilation and relinking for all clients of a library. This is anything but effective software <NOBR>design.<SCRIPT>create_link(17);</SCRIPT>
</NOBR></P><A NAME="46151"></A>
<P><A NAME="dingp18"></A>
On the same topic, a different author <NOBR>writes:<SCRIPT>create_link(18);</SCRIPT>
</NOBR></P><A NAME="46155"></A>
<A NAME="dingp19"></A><BLOCKQUOTE>If a public base class does not have a virtual destructor, no derived class nor members of a derived class should have a destructor.<SCRIPT>create_link(19);</SCRIPT>
</BLOCKQUOTE>
<A NAME="46158"></A>
<P><A NAME="dingp20"></A>

⌨️ 快捷键说明

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