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

📄 chapter01.html

📁 《C++编程思想》中文版。。。。。。。。。。。。。
💻 HTML
📖 第 1 页 / 共 5 页
字号:
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Aristotle was probably the first to begin
a careful study of the concept of <I>type</I>; he spoke of &#8220;the class of
fishes and the class of birds.&#8221; The idea that all objects, while being
unique, are also part of a class of objects that have characteristics and
behaviors in common was used directly in the first object-oriented language,
Simula-67, with its fundamental keyword <B>class</B> that introduces a new type
into a program.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><A NAME="Index79"></A><A NAME="Index80"></A><FONT FACE="Georgia">Simula,
as its name implies, was created for developing simulations such as the classic
&#8220;bank teller
problem</FONT><A NAME="fnB5" HREF="#fn5">[5]</A><FONT FACE="Georgia">.&#8221; In
this, you have a bunch of tellers, customers, accounts, transactions, and units
of money &#8211; a lot of &#8220;objects.&#8221; Objects that are identical
except for their state during a program&#8217;s execution are grouped together
into &#8220;classes of objects&#8221; and that&#8217;s where the
<A NAME="Index81"></A><A NAME="Index82"></A>keyword <B>class</B> came from.
Creating abstract data types (classes) is a fundamental concept in
object-oriented programming. Abstract data types work almost exactly like
built-in types: You can create variables of a type (called <I>objects </I>or
<I>instances</I> in object-oriented parlance) and manipulate those variables
(called <A NAME="Index83"></A><A NAME="Index84"></A><I>sending messages</I> or
<A NAME="Index85"></A><I>requests</I>; you send a message and the object figures
out what to do with it). The members (elements) of each class share some
commonality: every account has a balance, every teller can accept a deposit,
etc. At the same time, each member has its own state, each account has a
different balance, each teller has a name. Thus, the tellers, customers,
accounts, transactions, etc., can each be represented with a unique entity in
the computer program. This entity is the object, and each object belongs to a
particular class that defines its characteristics and
behaviors.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">So, although what we really do in
object-oriented programming is create new data types, virtually all
object-oriented programming languages use the &#8220;class&#8221; keyword. When
you see the word &#8220;type&#8221; think &#8220;class&#8221; and vice
versa</FONT><A NAME="fnB6" HREF="#fn6">[6]</A><FONT FACE="Georgia">.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Since a class describes a set of objects
that have identical characteristics (data elements) and behaviors
(functionality), a class is really a
<A NAME="Index86"></A><A NAME="Index87"></A>data type because a floating point
number, for example, also has a set of characteristics and behaviors. The
difference is that a programmer defines a class to fit a problem rather than
being forced to use an existing data type that was designed to represent a unit
of storage in a machine. You extend the programming language by adding new data
types specific to your needs. The programming system welcomes the new classes
and gives them all the care and type-checking that it gives to built-in
types.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The object-oriented approach is not
limited to building simulations. Whether or not you agree that any program is a
simulation of the system you&#8217;re designing, the use of OOP techniques can
easily reduce a large set of problems to a simple solution.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Once a class is established, you can make
as many objects of that class as you like, and then manipulate those objects as
if they are the elements that exist in the problem you are trying to solve.
Indeed, one of the challenges of object-oriented programming is to create a
one-to-one mapping between the elements in the problem space and objects in the
solution space.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">But how do you get an object to do useful
work for you? There must be a way to make a request of the object so that it
will do something, such as complete a transaction, draw something on the screen
or turn on a switch. And each object can satisfy only certain requests. The
requests you can make of an object are defined by its <I>interface</I>, and the
type is what determines the interface. A simple example might be a
representation of a light bulb: </FONT><BR></P></DIV>
<DIV ALIGN="CENTER"><FONT FACE="Georgia"><IMG SRC="TIC2Vo03.gif"></FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE>Light lt;
lt.on(); </PRE></FONT></BLOCKQUOTE>

<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The interface establishes <I>what</I>
requests you can make for a particular object. However, there must be code
somewhere to satisfy that request. This, along with the hidden data, comprises
the <A NAME="Index88"></A><I>implementation</I>. From a procedural programming
standpoint, it&#8217;s not that complicated. A type has a function associated
with each possible request, and when you make a particular request to an object,
that function is called. This process is usually summarized by saying that you
&#8220;send a message&#8221; (make a request) to an object, and the object
figures out what to do with that message (it executes code).</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Here, the name of the type/class is
<B>Light</B>, the name of this particular <B>Light </B>object is <B>lt</B>,<B>
</B>and the requests that you can make of a <B>Light</B> object are to turn it
on, turn it off, make it brighter or make it dimmer. You create a <B>Light
</B>object by declaring a name (<B>lt</B>) for that object. To send a message to
the object, you state the name of the object and connect it to the message
request with a period (dot). From the standpoint of the user of a pre-defined
class, that&#8217;s pretty much all there is to programming with
objects.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The diagram shown above follows the
format of the <A NAME="Index89"></A><A NAME="Index90"></A><I>Unified Modeling
Language</I> (UML). Each class is represented by a box, with the type name in
the top portion of the box, any data members that you care to describe in the
middle portion of the box, and the
<A NAME="Index91"></A><A NAME="Index92"></A><I>member functions</I> (the
functions that belong to this object, which receive any messages you send to
that object) in the bottom portion of the box. Often, only the name of the class
and the public member functions are shown in UML design diagrams, and so the
middle portion is not shown. If you&#8217;re interested only in the class name,
then the bottom portion doesn&#8217;t need to be shown,
either.</FONT><A NAME="_Toc375545190"></A><A NAME="_Toc408018387"></A><A NAME="_Toc472654684"></A><BR></P></DIV>
<A NAME="Heading23"></A><FONT FACE = "Verdana"><H2 ALIGN="LEFT">
The hidden implementation</H2></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">It is helpful to break up the playing
field into <A NAME="Index93"></A><I>class creators</I> (those who create new
data types) and <A NAME="Index94"></A><A NAME="Index95"></A><I>client
programmers</I></FONT><A NAME="fnB7" HREF="#fn7">[7]</A><A NAME="Index96"></A><FONT FACE="Georgia">
(the class consumers who use the data types in their applications). The goal of
the client programmer is to collect a toolbox full of classes to use for rapid
application development. The goal of the class creator is to build a class that
exposes only what&#8217;s necessary to the client programmer and keeps
everything else hidden. Why? Because if it&#8217;s hidden, the client programmer
can&#8217;t use it, which means that the class creator can change the hidden
portion at will without worrying about the impact to anyone else. The hidden
portion usually represents the tender insides of an object that could easily be
corrupted by a careless or uninformed client programmer, so hiding the
implementation reduces program bugs. The concept of
<A NAME="Index97"></A><A NAME="Index98"></A>implementation hiding cannot be
overemphasized.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">In any relationship it&#8217;s important
to have boundaries that are respected by all parties involved. When you create a
library, you establish a relationship with the client<I> </I>programmer, who is
also a programmer, but one who is putting together an application by using your
library, possibly to build a bigger library.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">If all the members of a class are
available to everyone, then the client programmer can do anything with that
class and there&#8217;s no way to enforce rules. Even though you might really
prefer that the client programmer not directly manipulate some of the members of
your class, without access control there&#8217;s no way to prevent it.
Everything&#8217;s naked to the world.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">So the first reason for access control is
to keep client programmers&#8217; hands off portions they shouldn&#8217;t touch
&#8211; parts that are necessary for the internal machinations of the data type
but not part of the interface that users need in order to solve their particular
problems. This is actually a service to users because they can easily see
what&#8217;s important to them and what they can ignore.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The second reason for access control is
to allow the library designer to change the internal workings of the class
without worrying about how it will affect the client programmer. For example,
you might implement a particular class in a simple fashion to ease development,
and then later discover that you need to rewrite it in order to make it run
faster. If the interface and implementation are clearly separated and protected,
you can accomplish this easily and require only a relink by the
user.<A NAME="Index99"></A><A NAME="Index100"></A><A NAME="Index101"></A></FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">C++ uses three explicit keywords to set
the boundaries in a class: <B>public</B>, <B>private</B>, and <B>protected</B>.
Their use and meaning are quite straightforward. These <I>access specifiers</I>
<A NAME="Index102"></A><A NAME="Index103"></A><A NAME="Index104"></A>determine
who can use the definitions that follow. <B>public</B>
<A NAME="Index105"></A>means the following definitions are available to
everyone. The <B>private</B> <A NAME="Index106"></A>keyword, on the other hand,
means that no one can access those definitions except you, the creator of the
type, inside member functions of that type. <B>private</B> is a brick wall
between you and the client programmer. If someone tries to access a
<B>private</B> member, they&#8217;ll get a compile-time error.
<A NAME="Index107"></A><B>protected</B> acts just like <B>private</B>, with the
exception that an inheriting class has access to <B>protected</B> members, but
not <B>private</B> members. Inheritance will be introduced
shortly.</FONT><A NAME="_Toc375545191"></A><A NAME="_Toc408018388"></A><A NAME="_Toc472654685"></A><BR></P></DIV>
<A NAME="Heading24"></A><FONT FACE = "Verdana"><H2 ALIGN="LEFT">
Reusing the implementation</H2></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Once a class has been created and tested,
it should (ideally) represent a useful unit of code. It turns out that this
<A NAME="Index108"></A>reusability is not nearly so easy to achieve as many
would hope; it takes experience and insight to produce a good design. But once
you have such a design, it begs to be reused. Code reuse is one of the greatest
advantages that object-oriented programming languages provide.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The simplest way to reuse a class is to
just use an object of that class directly, but you can also place an object of
that class inside a new class. We call this &#8220;creating a
<A NAME="Index109"></A><A NAME="Index110"></A>member object.&#8221; Your new
class can be made up of any number and type of other objects, in any combination
that you need to achieve the functionality desired in your new class. Because
you are composing a new class from existing classes, this concept is called
<A NAME="Index111"></A><I>composition</I> (or more generally,
<A NAME="Index112"></A><I>aggregation</I>). Composition is often referred to as
a &#8220;<A NAME="Index113"></A>has-a&#8221; relationship, as in &#8220;a car
has an engine.&#8221;</FONT><BR></P></DIV>
<DIV ALIGN="CENTER"><FONT FACE="Georgia"><IMG SRC="TIC2Vo04.gif"></FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">(The above <A NAME="Index114"></A>UML
diagram indicates composition with the filled diamond, which states there is one
car. I will typically use a simpler form: just a line, without the diamond, to
indicate an
association.</FONT><A NAME="fnB8" HREF="#fn8">[8]</A><FONT FACE="Georgia">)</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Composition comes with a great deal of
flexibility. The member objects of your new class are usually private, making
them inaccessible to the client programmers who are using the class. This allows
you to change those members without disturbing existing client code. You can

⌨️ 快捷键说明

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