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

📄 ch05.htm

📁 c++语言操作手册
💻 HTM
📖 第 1 页 / 共 5 页
字号:
<!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 5 - Object-Oriented Programming and Design</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">5</H1><h1 align="center"> Object-Oriented Programming and Design</h1><address>by Danny Kalev </address><ul>  <li><a href="#Heading1">Introduction</a>   <li><a href="#Heading2">Programming Paradigms</a>     <ul>      <li><a href="#Heading3">Procedural Programming</a>       <li><a href="#Heading4">Object-Based Programming</a>       <li><a href="#Heading5">Object-Oriented Programming</a>     </ul>  <li><a href="#Heading6">Techniques Of Object-Oriented Programming</a>     <ul>      <li><a href="#Heading7">Class Design</a>       <li><a href="#Heading8">The "Resource Acquisition Is Initialization" Idiom</a>     </ul>  <li><a href="#Heading9">Classes and Objects</a>   <li><a href="#Heading10">Designing Class Hierarchies</a>     <ul>      <li><a href="#Heading11">Private Data Members Are Preferable To Protected         Ones</a>       <li><a href="#Heading12">Declaring Virtual Base Class Destructors</a>       <li><a href="#Heading13">Virtual Member Functions</a>       <li><a href="#Heading14">Abstract Classes and Interfaces</a>       <li><a href="#Heading15">Use Derivation Instead of Type-Fields</a>       <li><a href="#Heading16">Overloading A Member Function Across Class Boundaries</a>       <li><a href="#Heading17">Deciding Between Inheritance and Containment</a>       <li><a href="#Heading18">The Holds-a Relation</a>       <li><a href="#Heading19">Empty Classes</a>       <li><a href="#Heading20">Using structs as A Shorthand for Public Classes</a>       <li><a href="#Heading21">Friendship</a>       <li><a href="#Heading22">Nonpublic Inheritance</a>       <li><a href="#Heading23">Common Root Class</a>       <li><a href="#Heading24">Forward Declarations</a>       <li><a href="#Heading25">Local Classes</a>       <li><a href="#Heading26">Multiple Inheritance</a>     </ul>  <li><a href="#Heading27">Conclusions</a> </ul><hr size=4><h2> <a name="Heading1">Introduction</a></h2><p>C++ is the most widely used object-oriented programming language today. The   success of C++ has been a prominent factor in making object-oriented design   and programming a de facto standard in today's software industry. Yet, unlike   other object-oriented programming languages (some of them have been around for   nearly 30 years), C++ does not enforce object-oriented programming -- it can   be used as a "better C", as an <i>object-based</i> language, or as a generic   programming language. This flexibility, which is unparalleled among programming   languages, makes C++ a suitable programming language in any domain area -- real   time, embedded systems, data processing, numerical computation, graphics, artificial   intelligence, or system programming.</p><p>This chapter begins with a brief survey of the various programming styles that   are supported by C++. Next, you will focus on various aspects of object-oriented   design and programming.</p><h2> <a name="Heading2">Programming Paradigms</a></h2><p>A programming paradigm defines the methodology of designing and implementing   software, including the building blocks of the language, the interaction between   data structures and the operations applied to them, program structure, and how   problems are generally analyzed and solved. A programming language provides   the linguistic means (keywords, preprocessor directives, program structure)   as well as the extra-linguistic capabilities, namely standard libraries and   programming environment, to support a specific programming paradigm. Usually,   a given programming language is targeted for a specific application domain,   for example, string manipulation, mathematical applications, simulations, Web   programming and so on. C++, however, is not confined to any specific application   domain. Rather, it supports many useful programming paradigms. Now, for a discussion   of some of the most prominent programming paradigms supported in C++.</p><h3> <a name="Heading3">Procedural Programming</a></h3><p>C++ is a superset of ISO C. As such, it can be used as a procedural programming   language, albeit with tighter type checking and several enhancements that improve   design and coding: reference variables, inline functions, default arguments,   and <tt>bool</tt> type. Procedural programming is based on separation between   functions and the data that they manipulate. In general, functions rely on the   physical representation of the data types that they manipulate. This dependency   is one of the most problematic aspects in the maintenance and extensibility   of procedural software.</p><h4> Procedural Programming Is Susceptible To Design Changes</h4><p>Whenever the definition of a type changes (as a result of porting the software   to a different platform, changes in the customer's requirement, and so on),   the functions that refer to that type have to be modified accordingly. The opposite   is also true: When a function is being changed, its arguments might be affected   as well; for instance, instead of passing a struct by value, it might be passed   by address to optimize performance. Consider the following:</p><pre><tt>struct Date //pack data in a compact struct</tt><tt>{</tt><tt>  char day;</tt><tt>  char month;</tt><tt>  short year;</tt><tt>};</tt><tt>bool isDateValid(Date d); //pass by value</tt><tt>void getCurrentDate(Date * pdate); //changes its argument, address needed</tt><tt>void initializeDate (Date* pdate); //changes its argument, address needed</tt></pre><p>Data structures, such as <tt>Date</tt>, and the group of associated functions   that initialize, read, and test it are very common in software projects in which   C is the predominant programming language. Now suppose that due to a change   in the design, <tt>Date</tt> is required to also hold the current time stamp   in seconds. Consequently, a change in the definition of <tt>Date</tt> is made:</p><pre><tt>struct Date</tt><tt>{</tt><tt>  char day;</tt><tt>  char month;</tt><tt>  short year;</tt><tt>  long seconds;</tt><tt>}; //now less compact than before</tt></pre><p>All the functions that manipulate <tt>Date</tt> have to be modified to cope   with change. An additional change in the design adds one more field to store   millionths of a second in order to make a unique timestamp for database transactions.   The modified <tt>Date</tt> is now</p><pre><tt>struct Date</tt><tt>{</tt><tt>  char day;</tt><tt>  char month;</tt><tt>  short year;</tt><tt>  long seconds;</tt><tt>  long millionths;</tt><tt>};</tt></pre><p>Once more, all the functions that manipulate <tt>Date</tt> have to be modified   to cope with the change. This time, even the interface of the functions changes   because <tt>Date</tt> now occupies at least 12 bytes. Functions that are passed   a <tt>Date</tt> by value are modified to accept a pointer to <tt>Date</tt>.</p><pre><tt>bool isDateValid(Date* pd); // pass by address for efficiency</tt></pre><h4> Drawbacks of Procedural Programming</h4><p>This example is not fictitious. Such frequent design changes occur in almost   every software project. The budget and time overhead that are produced as a   result can be overwhelming; indeed, they sometimes lead to the project's discontinuation.   The attempt to avoid -- or at least to minimize -- these overheads has led to   the emergence of new programming paradigms.</p><p>Procedural programming enables only a limited form of code reuse, that is,   by calling a function or using a common user-defined data structure. Nonetheless,   the tight coupling between a data structure and the functions that manipulate   it considerably narrows their reusability potential. A function that computes   the square root of a <tt>double</tt> cannot be applied to a user-defined <tt>struct</tt>   that represents a <tt>complex</tt>, for example. In general, procedural programming   languages rely on static type checking, which ensures better performance than   dynamic type checking -- but it also compromises the software's extensibility.</p><p>Procedural programming languages provide a closed set of built-in data types   that cannot be extended. User-defined types are either unsupported or they are   "second class citizens" in the language. The user cannot redefine built-in operators   to support them. Furthermore, the lack of abstraction and information hiding   mechanisms force users to expose the implementation details. Consider the standard   C functions <tt>atof()</tt>, <tt>atoi()</tt>, and <tt>atol()</tt>, which convert   a C-string to <tt>double</tt>, <tt>int</tt>, and <tt>long</tt>, respectively.   Not only do they force the user to pay attention to the physical data type of   the return value (on most machines these days, an <tt>int</tt> and a <tt>long</tt>   are identical anyway), they also prohibit the use of other data types.</p><h4> Why Procedural Programming Still Matters</h4><p>In spite of its noticeable drawbacks, procedural programming is still the preferred   programming paradigm in some specific application domains, such as embedded   and time critical systems. Procedural programming is also widely used in machine   generated code because code reuse, extensibility, and maintenance are immaterial   in this case. Many SQL interpreters, for example, translate the high-level SQL   statements into C code that is then compiled.</p><p>Procedural programming languages -- such as C, Pascal, or Fortran -- produce   the most efficient machine code among high-level programming languages. In fact,   development teams that are reluctant to adopt object orientation often point   to performance degradation as the major deterring factor.</p><p>The evolution of C++ is unique among programming languages. The job of its   creators might have been a lot easier had they chosen to design it from scratch,   without guaranteeing backward compatibility with C. Yet this backward compatibility   is one of the its strengths: It enables organizations and programmers to benefit   from C++ without having to trash hundreds of millions of lines of working C   code. Furthermore, C programmers can easily become productive in C++ even before   they have fully mastered object-oriented programming.</p><h3> <a name="Heading4">Object-Based Programming</a></h3><p>The limitations of procedural programming have led researchers and developers   alike to find better methods of separating implementation details from interfaces.   Object-based programming enables them to create user-defined types that behave   like first class citizens. User-defined types can bundle data and meaningful   operations in a single entity -- a <i>class</i>. Classes also support information   hiding, thereby separating implementation details such as physical representation   and underlying bookkeeping from the set of services that a class provides, or   its <i>interface</i>. Users of a class are allowed to access its interface,   but they cannot access its implementation details. The separation between the   implementation -- which might vary rather frequently due to design changes,   portability, and efficiency -- and the stable interface is substantial. This   separation ensures that changes in the design are localized to a single entity   -- the class implementation; the class users, on the other hand, are not affected.   To assess the importance of object-based programming, examine a simple minded   <tt>Date</tt> class:</p><pre><tt>class Date</tt><tt>{</tt><tt>private:</tt><tt>  char day;</tt><tt>  char month;</tt><tt>  short year;</tt><tt>public:</tt><tt>  bool isValid();</tt><tt>  Date getCurrent();</tt><tt>  void initialize();</tt><tt>};</tt></pre><h4> Object-Based Programming Localizes Changes In Implementation Details</h4><p>Now suppose that you have to change the definition of <tt>Date</tt> to support   time:</p><pre><tt>class Date</tt><tt>{</tt><tt>private:</tt><tt>  char day;</tt><tt>  char month;</tt><tt>  short year;</tt><tt>  long secs;</tt><tt>public:</tt><tt>  bool isValid();</tt><tt>  Date getCurrent();</tt><tt>  void initialize ();</tt><tt>};</tt></pre><p>The addition of a new data member does not affect the interface of <tt>Date</tt>.   The users of <tt>Date</tt> don't even know that a new field has been added;   they continue to receive the same services from the class as before. Of course,   the implementer of <tt>Date</tt> has to modify the code of the member functions   to reflect the change. Therefore, <tt>Date::initialize()</tt> has to initialize   one more field. Still, the change is localized only to the definition of <tt>Date::initialize()</tt>   because users cannot access the underlying representation of <tt>Date</tt>.   In procedural programming, however, users can access the data members of <tt>Date</tt>   directly.</p><h4> Abstract Data Types</h4><p>Classes such as <tt>Date</tt> are sometimes called <i>concrete types,</i> or   <i>abstract data types</i> (not to be confused with <i>abstract classes</i>;   see the sidebar titled "Abstract Data Types Versus Abstract Classes" later in   this chapter). </p><p>These classes can meet a vast variety of needs in clean and easy-to-maintain 

⌨️ 快捷键说明

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