基于无线传感网络的车位引导系统外文翻译资料

 2022-08-27 10:17:48

. Introducing Classes

The only remaining feature we need to understand before solving our bookstore problem is how to write a data structure to represent our transaction data. In C we define our own data structure by defining a class. The class mechanism is one of the most important features in C . In fact, a primary focus of the design of C is to make it possible to define class types that behave as naturally as the built-in types themselves. The library types that weve seen already, such as istream and ostream, are all defined as classesthat is,they are not strictly speaking part of the language.

Complete understanding of the class mechanism requires mastering a lot of information. Fortunately, it is possible to use a class that someone else has written without knowing how to define a class ourselves. In this section, well describe a simple class that we canuse in solving our bookstore problem. Well implement this class in the subsequent chapters as we learn more about types,expressions, statements, and functionsall of which are used in defining classes.

To use a class we need to know three things: What is its name? Where is it defined?

What operations does it support?

For our bookstore problem, well assume that the class is named Sales_item and that it is defined in a header named Sales_item.h. The Sales_item Class

The purpose of the Sales_item class is to store an ISBN and keep track of the number of copies sold, the revenue, and average sales price for that book. How these data are stored or computed is not our concern. To use a class, we need not know anything about how it is implemented. Instead, what we need to know is what operations the class provides.

As weve seen, when we use library facilities such as IO, we must include the associated headers. Similarly, for our own classes, we must make the definitions associated with the class available to the compiler. We do so in much the same way. Typically, we put the class definition into a file. Any program that wants to use our class must include that file.

Conventionally, class types are stored in a file with a name that, like the name of a program source file, has two parts: a file name and a file suffix. Usually the file name is the same as the class defined in the header. The suffix usually is .h, but some programmers use .H, .hpp, or .hxx. Compilers usually arent picky about header file names, but IDEs

sometimes are. Well assume that our class is defined in a file named Sales_item.h. Operations on Sales_item Objects

Every class defines a type. The type name is the same as the name of the class. Hence, our Sales_item class defines a type named

Sales_item. As with the built-in types, we can define a variable of a class type. When we write 'Sales_item item' we are saying that item is an object of type Sales_item. We often contract the phrase 'an object of type Sales_item' to'aSales_ item object' or even more simply to 'a Sales_item.'

In addition to being able to define variables of type Sales_item, we can perform the following operations on Sales_item objects:

Use the addition operator, , to add two Sales_items, Use the input operator, lt;lt; to read a Sales_item object, Use the output operator, gt;gt; to write a Sales_item object,

Use the assignment operator, =, to assign one Sales_item object to another,

Call the same_isbn function to determine if two Sales_items refer to the same book. Classes are central to most C programs: Classes let us define our own types that are customizedfor the problems we need to solve, resulting in applications that are easier to write and understand.Well-designed class types can be as easy to use as the built-in types. A class defines data and function members: The data members store the state associated with objectsof the class type, and the functions perform operations that give meaning to the data. Classeslet us separate implementation and interface. The interface specifies the operations that the classsupports. Only the implementor of the class need know or care about the details of the implementation. This separation reduces the bookkeeping aspects that make programming tedious anderror-prone.

Class types often are referred to as abstract data types. An abstract data type treats the data(state) and operations on that state as a single unit. We can think abstractly about what the classd oes, rather than always having to be aware of how the class operates. Abstract data types arefundamental to both object-oriented and generic programming.

Data abstraction is a programming (and design) technique that relies on the separation of interfaceand implementation. The class designer must worry about how a class is implemented, but programmersthat use the class need not know about these details. Instead, programmers who use a type need to know only the types interface; they can think abstractly about what the type does rather than concretely about how the type works.

Encapsulation is a term that describes the technique of combining lower-level elements to forma new, higher-level entity. A function is one form of encapsulation: The detailed actions performedby the function are encapsulated in the larger entity that is the function itself. Encapsulated elements hide the details of their implementationwe may calla function but have no access to the statements that it executes. In the same way, a class is an encapsulated entity: It represents an aggregation of several members, and most (well-designed) class types hide the members that implement the type.

If we think about the library vector type, it is an example of both data abstraction and encapsulation. It is abstract in that to use it, we think about its interfaceabout the operations that it can perform. It is encapsulated because we have no access to

剩余内容已隐藏,支付完成后下载完整资料


中文译文

类的简介

解决书店问题之前,还需要弄明白如何编写数据结构来表示交易数据。C 中我们通过定义类来定义自己的数据结构。类机制是 C 中最重要的特征之一。事实上,C 设计的主要焦点就是使所定义的类类型的行为可以像内置类型一样自然。我们前面已看到的像 istream 和 ostream 这样的库类型,都是定义为类的,也就是说,它们严格说来不是语言的一部分。

完全理解类机制需要掌握很多内容。所幸我们可以使用他人写的类而无需掌握如何定义自己的类。在这一节,我们将描述一个用于解决书店问题的简单类。当我们学习了更多关于类型、表达式、语句和函数的知识(所有这些在类定义中都将用到)后,将会在后面的章节实现这个类。 使用类时我们需要回答三个问题: 类的名字是什么? 它在哪里定义? 它支持什么操作?

对于书店问题,我们假定类命名为 Sales_item 且类定义在命名为 Sales_item.h 的头文件中。 Sales_item 类

Sales_item 类的目的是存储 ISBN 并保存该书的销售册数、销售收入和平均售价。我们不关心如何存储或计算这些数据。使用类时我们不需要知道这个类是怎样实现的,相反,我们需要知道的是该类提供什么操作。

正如我们所看到的,使用像 IO 一样的库工具,必须包含相关的头文件。类似地,对于自定义的类,必须使得编译器可以访问和类相关的定义。这几乎可以采用同样的方式。一般来说,我们将类定义放入一个文件中,要使用该类的任何程序都必须包含这个文件。

依据惯例,类类型存储在一个文件中,其文件名如同程序的源文件名一样,由文件名和文件后缀两部分组成。通常文件名和定义在头文件中的类名是一样的。通常后缀是 .h,但也有一些程序员用 .H、.hpp 或 .hxx。编译器通常并不挑剔头文件名,但 IDE 有时会。假设我们的类定义在名为 Sale_item.h 的文件中。 Sales_item 对象上的操作

每个类定义一种类型,类型名与类名相同。因此,我们的 Sales_item 类定义了一种命名为 Sales_item 的类型。像使用内置类型一样,可以定义类类型的变量。当写下' Sales_item item',就表示 item 是类型 Sales_item 的一个对象。通常将“类型 Sales_item 的一个对象”简称为“一个 Sales_item 对象”,或者更简单地简称为“一个 Sales_item”。 除了可以定义 Sales_item 类型的变量,我们还可以执行 Sales_item 对象的以下操作:

使用加法操作符, ,将两个 Sales_item 相加;

使用输入操作符,lt;lt;,来读取一个 Sales_item 对象; 使用输出操作符,gt;gt;,来输出一个 Sales_item 对象;

使用赋值操作符,=,将一个 Sales_item 对象赋值给另一个 Sales_item 对象;

调用 same_isbn 函数确定两个 Sales_item 是否指同一本书。 在大多数 C 程序中,类都是至关重要的:我们能够使用类来定义为要解决的问题定制的数据类型,从而得到更加易于编写和理解的应用程序。设计良好的类类型可以像内置类型一样容易使用。

类定义了数据成员和函数成员:数据成员用于存储与该类类型的对象相关联的状态,而函数成员则负责执行赋予数据意义的操作。通过类我们能够将实现和接口分离,用接口指定类所支持的操作,而实现的细节只需类的实现者了解或关心。这种分离可以减少使编程冗长乏味和容易出错的那些繁琐工作。 类类型常被称为抽象数据类型(abstract data types)。抽象数据类型将数据(即状态)和作用于状态的操作视为一个单元。我们可以抽象地考虑类该做什么,而无须知道何去完成这些操作。抽象数据类型是面向对象编程和泛型编程的基础。 数据抽象是一种依赖于接口和实现分离的编程(和设计)技术。类设计者必须关心类是如何实现的,但使用该类的程序员不必了解这些细节。相反,使用一个类型的程序员仅需了解类型的接口,他们可以抽象地考虑该类型做什么,而不必具体地考虑该类型如何工作。

封装是一项低层次的元素组合起来的形成新的、高层次实体珠技术。函数是封装的一种形式:函数所执行的细节行为被封装在函数本身这个更大的实体中。被封装的元素隐藏了它们的实现细节——可以调用一个函数但不能访问它所执行的语句。同样地,类也是一个封装的实体:它代表若干成员的聚焦,大多数(良好设计的)类类型隐藏了实现该类型的成员。 标准库类型 vector 同时具备数据抽象和封装的特性。在使用方面它是抽象的,只需考虑它的接口,即它能执行的操作。它又是封装的,因为我们既无法了解该类型如何表示的细节,也无法访问其任意的实现制品。另一方面,数组在概念上类似于 vector,但既不是抽象的,也不是封装的。可以通过访问存放数组的内存来直接操纵数组。

并非所有类型都必须是抽象的。标准库中的 pair 类就是一个实用的、设计良好的具体类而不是抽象类。具体类会暴露而非隐藏其实现细节。

一些类,例如 pair,确实没有抽象接口。pair 类型只是将两个数据成员捆绑成单个对象。在这种情况下,隐藏数据成员没有必要也没有明显的好处。在像 pair 这样的类中隐藏数据成员只会造成类型使用的复杂化。

尽管如此,这样的类型通常还是有成员函数。特别地,如果类具有内置类型或复合类型数据成员,那么定义构造函数来初始化这些成员就是一个好主意。类的使用都也可以初始化或赋值数据成员,但由类来做更不易出错。 程序员经常会将运行应用程序的人看作“用户”。应用程序为最终“使用”它的用户而设计,并响应用户的反馈而完善。类也类似:类的设计者为类的“用户”设计并实现类。在这种情况下,“用户”是程序员,而不是应用程序的最终用户。

成功的应用程序的创建者会很好地理解和实现用户的需求。同样地,良好设计的、实用的类,其设计也要贴近类用户的需求。

另一方面,类的设计者与实现者之间的区别,也反映了应用程序的用户与设计和实现者之间的区分。用户只关心应用程序能否以合理的费用满足他们的需求。同样地,类的使用者只关心它的接口。好的类设计者会定义直观和易用的类接口,而使用者只关心类中影响他们使用的部分实现。如果类的实现速度太慢或给类的使用者加上负担,则必然引起使用者的关注。在良好设计的类中,只有类的设计者会关心实现。 在简单的应用程序中,类的使用者和设计者也许是同一个人。即使在这种情况下,保持角色区分也是有益的。设计类的接口时,设计者应该考虑的是如何方便类的使用;使用类的时候,设计者就不应该考虑类如何工作。

提到“用户”时,应该由上下文清楚地标明所指的是哪类用户。如果提到“用户代码”或 Sales_item 类的”用户“,指的就是使用类编写应用程序的程序员。如果提到书店应用程序的”用户“,那么指的是运行应用程序的书店管理人员。 数据抽象和封装提供了两个重要优点:

1.避免类内部出现无意的、可能破坏对象状态的用户级错误。

2.随时间推移可以根据需求改变或缺陷(bug)报告来完美类实现,而无须改变用户级代码。

仅在类的私有部分定义数据成员,类的设计者就可以自由地修改数据。如果实现改变了,那么只需检查类代码来了解此变化可能造成的影响。如果数据为仅有的,则任何直接访问原有数据成员的函数都可能遭到破坏。在程序可重新使用之前,有必要定位和重写依赖原有表示的那部分代码。

同样地,如果类的内部状态是私有的,则数据成员的改变只可能在有限的地方发生。避免数据中出现用户可能引入的错误。如果有缺陷会破坏对象的状态,就在局部位置搜寻缺陷:如果数据是私有的,那么只有成员函数可能对该错误负责。对错误的搜寻是有限的,从而大大方便了程序的维护和修正。

如果数据是私有的并且没有改变成员函数的接口,则操纵类对象的用户函数无须改变。

改变头文件中的类定义可有效地改变包含该头文件的每个源文件的程序文本,所以,当类发生改变时,使用该类的代码必须重新编译。 类是 C 中最基本的特征,允许定义新的类型以适应应用程序的需要,同时使程序更短且更易于修改。

数据抽象是指定义数据和函数成员的能力,而封装是指从常规访问中保护类成员的能力,它们都是类的基础。成员函数定义类的接口。通过将类的实现所用到的数据和函数设置为 private 来封装类。

类可以定义构造函数,它们是特殊的成员函数,控制如何初始化类的对象。可以重载构造函数。每个构造函数就初始化每个数据成员。初始化列表包含的是名—值对,其中的名是一个成员,而值则是该成员的初始值。

类可以将对其非 public 成员的访问权授予其他类或函数,并通过将其他的类或函数设为友元来授予其访问权。

类也可以定义 mutable 或 static 成员。mutable 成员永远都不能为 const;它的值可以在 const 成员函数中修改。static 成员可以是函数或数据,独立于类类型的对象而存在。

拷贝控制

每种类型,无论是内置类型还是类类型,都对该类型对象的一组(可能为空的)操作的含义进行了定义。比如,我们可以将两个 int 值相加,运行 vector 对象的 size 操作,等等。这些操作定义了用给定类型的对象可以完成什么任务。

每种类型还定义了创建该类型的对象时会发生什么——构造函数定义了该类类型对象的初始化。类型还能控制复制、赋值或撤销该类型的对象时会发生什么——类通过特殊的成员函数:复制构造函数、赋值操作符和析构函数来控制这些行为。本章将介绍这些操作。

当定义一个新类型的时候,需要显式或隐式地指定复制、赋值和撤销该类型的对象时会发生什么——这是通过定义特殊成员:复制构造函数、赋值操作符和析构函数来达到的。如果没有显式定义复制构造函数或赋值操作符,编译器(通常)会为我们定义。

拷贝构造函数是一种特殊构造函数,具有单个形参,该形参(常用 const 修饰)是对该类类型的引用。当定义一个新对象并用一个同类型的对象对它进行初始化时,将显式使用复制构造函数。当将该类型的对象传递给函数或函数返回该类型的对象时,将隐式使用复制构造函数。

复制构造函数、赋值操作符和析构函数总称为复制控制。编译器自动实现这些操作,但类也可以定义自己的版本。

复制控制是定义任意 C 类必不可少的部分。初学 C 的程序员常对必须定义在复制、赋值或撤销对象时发生什么感到困惑。因为如果我们没有显式定义这些操作,编译器将为我们定义它们(尽管它们也许不像我们期望的那样工作),这往往使初学者更加困惑。

通常,编译器合成的复制控制函数是非常精练的——它们只做必需的工作。但对某些类而言,依赖于默认定义会导致灾难。实现复制控制操作最困难的部分,往往在于识别何时需要覆盖默认版本。有一种特别常见的情况需要类定义自己的复制控制成员的:类具有指针成员。

拷贝构造函数

只有单个形参,而且该形参是对本类类型对象的引用(常用 const 修饰),这样的构造函数称为复制构造函数。与默认构造函数一样,复制构造函数可由编译器隐式调用。复制构造函数可用于:

1.根据另一个同类型的对象显式或隐式初始化一个对象。 2.复制一个对象,将它作为实参传给一个函数。 3.从函数返回时复制一个对象。 4.初始化顺序容器中的元素。 5.根据元素初始化式列表初始化数组元素。 对象的定义形式

回忆一下,C 支持两种初始化形式(第 2.3.3 节):直接初始化和复制初始化。复制初始化使用 = 符号,而直接初始化将初始化式放在圆括号中。

当用于类类型对象时,初始化的复制形式和直接形式有所不同:直接初始化直接调用与实参匹配的构造函数,复制初始化总是调用复制构造函数。复制初始化首先使用指定构造函数创建一个临时对象(第 7.3.2 节),然后用复制构造函数将那个临时对象复制到正在创建的对象:

string null_book = '9-999-99999-9'; // copy-initialization string dots(10, .); // direct-initialization string empty_copy = string(); // copy-initialization string empty_direct; // direct-initialization 对于类类型对象,只有指定单个实参或显式创建一个临时对象用于复制时,才使用复制初始化。 创建 dots 时,调用参数为一个数量和一个字符的 string 构造函数并直接初始化 dots 的成员。创建 null_book 时,编译器首先调用接受一个 C 风格字符串形参的 string 构造函数,创建一个临时对象,然后,编译器使用 string 复制构造函数将 null_book 初始化为那个临时对象的副本。 empty_copy 和 empty_direct 的初始化都调用默认构造函数。对前者初始化时,默认构造函数函数创建一个临时对象,然后复制构造函数用该对象初始化 empty_copy。对后者初始化时,直接

剩余内容已隐藏,支付完成后下载完整资料


资料编号:[499927],资料为PDF文档或Word文档,PDF文档可免费转换为Word

原文和译文剩余内容已隐藏,您需要先支付 30元 才能查看原文和译文全部内容!立即支付

以上是毕业论文外文翻译,课题毕业论文、任务书、文献综述、开题报告、程序设计、图纸设计等资料可联系客服协助查找。