Object-oriented programming (OOP) is a particular conceptual approach to designing programs,and C++ has enhanced C with features that ease the way to applying that approach.The following are the most important OOP features:
- Abstraction
- Encapsulation and data hiding
- Polymorphism
- Inheritance
- Reusability of code
1 Abstraction and Classes
1.1 Classes in C++(完成)
A class is a C++ vehicle for translating an abstraction to a user-defined type. It combines data representation and methods for manipulating that data into one simple package. Let’s look at a class that represents stocks.
First, you have to think a bit about how to represent stocks.You could take one share of stock as the basic unit and define a class to represent a share. However, that implies that you would need 100 objects to represent 100 shares,and that’s not practical. Instead, you can represent a person’s current holdings in a particular stock as a basic unit.The number of shares owned would be part of the data representation.A realistic approach would have to maintain records of such things as initial purchase price and date of purchase for tax purposes.Also it would have to manage events such as stock splits.That seems a bit ambitious for a first effort at defining a class, so you can instead take an idealized, simplified view of matters. In particular, you can limit the operations you can perform to the following:
- Acquire stock in a company.
- Buy more shares of the same stock.
- Sell stock.
- Update the per-share value of a stock.
- Display information about the holdings.
You can use this list to define the public interface for the stock class. (And you can add additional features later if you’re interested.) To support this interface, you need to store some information.Again, you can use a simplified approach. For example, don’t worry about the U.S. practice of evaluating stocks in multiples of eighths of a dollar. Here’s a list of information to store:
- Name of company
- Number of stocks owned
- Value of each share
- Total value of all shares
Next, you can define the class. Generally,a class specification has two parts:
- A class declaration, which describes the data component, in terms of data members, and the public interface, in terms of member functions, termed methods
- The class method definitions, which describe how certain class member functions are implemented
Roughly speaking, the class declaration provides a class overview, whereas the method definitions supply the details.
What Is an Interface?
An interface is a shared framework for interactions between two systems—for instance, between a computer and a printer or between a user and a computer program. For example, the user might be you and the program might be a word processor. When you use the word
processor, you don’t transfer words directly from your mind to the computer memory. Instead, you interact with the interface provided by the program. You press a key, and the computer shows you a character on the screen. You move the mouse, and the computer
moves a cursor on the screen. You click the mouse accidentally, and something weird happens to the paragraph you were typing. The program interface manages the conversion of your intentions to specific information stored in the computer.
For classes, we speak of the public interface. In this case, the public is the program using the class, the interacting system consists of the class objects, and the interface consists of the methods provided by whoever wrote the class. The interface enables you, the programmer, to write code that interacts with class objects, and thus it enables the program to use the class objects. For example, to find the number of characters in astringobject, you don’t open up the object to what is inside; you just use thesize()method provided by the class creators. It turns out that the class design denies direct access to the public user. But the public is allowed to use thesize()method. Thesize()method, then, is part of the public interface between the user and astringclass object. Similarly, thegetline()
method is part of theistreamclass public interface; a program usingcindoesn’t tinker directly with the innards of acinobject to read a line of input; instead,getline()does the work.
If you want a more personal relationship, instead of thinking of the program using a class as the public user, you can think of the person writing the program using the class as the public user. But in any case, to use a class, you need to know its public interface; to write a class, you need to create its public interface.
Developing a class and a program using it requires several steps. Rather than take them all at once, let’s break up the development into smaller stages.Typically, C++ programmers place the interface, in the form of a class definition, in a header file and place the implementation, in the form of code for the class methods, in a source code file. So let’s be typical. Listing 10.1 presents the first stage,a 暂时性的 class declaration for a class called Stock. The file uses #ifndef,and so on,as described in Chapter 9,“Memory Models and Namespaces,” to protect against multiple file inclusions.
Listing 10.1 看起来像一个结构声明,但是增加了一些额外的细节, such as member functions and public and private sections. We’ll improve on this declaration shortly, but first let’s see how this definition works.
// Listing 10.1 stock00.h
// stock00.h -- Stock class interface
// version 00
#ifndef STOCK00_H_
#define STOCK00_H_
#include <string>
class Stock{
private:
std::string company;
long shares;
double share_val;
double total_val;
void set_tot() { total_val = shares * share_val; }
public:
void acquire(const std::string & co, long n, double pr);
void buy(long num, double price);
void sell(long num, double price);
void update(double price);
void show();
};
#endif
To begin, the C++ keyword class identifies the code in Listing 10.1 as defining the design of a class. The syntax identifies Stock as the type name for this new class.This declaration enables you to declare variables, called objects, or instances, of the Stock type. Each individual object represents a single holding. For example, the following declarations create two Stock objects called sally and solly:
Stock sally;
Stock solly;
The sally object, for example, could represent Sally’s stock holdings in a particular company.
Next, notice that the information you decided to store appears in the form of class data members, such as company and shares.The company member of sally, for example, holds the name of the company, the share member holds the number of shares Sally owns, the share_val member holds the value of each share,and the total_val member holds the total value of all the shares. Similarly, the desired operations appear as class function members (or methods), such as sell() and update(). A member function can be defined in place—for example, set_tot()—or it can be represented by a prototype, like the other member functions in this class.The full definitions for the other member functions come later in the implementation file, but the prototypes suffice to describe the function interfaces.The binding of data and methods into a single unit is the most striking feature of the class. Because of this design, creating a Stock object automatically establishes the rules governing how that object can be used.
You’ve already seen how the istream and ostream classes have member functions, such as get() and getline().The function prototypes in the Stock class declaration demonstrate how member functions are established.The iostream header file, for example, has a getline() prototype in the istream class declaration
1.1.1 Access Control(完成)
Also new are the keywords private and public.These labels describe access control for class members. Any program that uses an object of a particular class can access the public portions directly. A program can access the private members of an object only by using the public member functions or via a friend function. For example, the only way to alter the shares member of the Stock class is to use one of the Stock member functions.Thus, the public member functions act as go-betweens between a program and an object’s private members; they provide the interface between object and program.This insulation of data from direct access by a program is called data hiding. (See Figure 10.1.)

A class design attempts to separate the public interface from the specifics of the implementation.The public interface represents the abstraction component of the design. Gathering the implementation details together and separating them from the abstraction is called encapsulation(封装). Data hiding (putting data into the private section of a class) is an instance of encapsulation,and so is hiding functional details of an implementation in the private section,as the Stock class does with set_tot(). Another example of encapsulation is the usual practice of placing class function definitions in a separate file from the class declaration.
Note that data hiding not only prevents you from accessing data directly, but it also frees you from needing to know how the data is represented. For example, the show() member displays,among other things, the total value of a holding.This value can be stored as part of an object, as the code in Listing 10.1 does, or it can be calculated when needed. From the standpoint of using the class, it makes no difference which approach is used. What you do need to know is what the different member functions accomplish; that is, you need to know what kinds of arguments a member function takes and what kind of return value it has.The principle is to separate the details of the implementation from the design of the interface. If you later find a better way to implement the data representation or the details of the member functions, you can change those details without changing the program interface,and that makes programs much easier to maintain.
1.1.2 Member Access Control: Public or Private?(完成)
You can declare class members, whether they are data items or member functions, either in the public or the private section of a class. But because one of the main precepts of OOP is to hide the data, data items normally go into the private section. 构成类接口的member functions应该放在public部分;否则在程序中无法调用这些函数。As the Stock declaration shows, you can also put member functions in the private section.You can’t call such functions directly from a program, but the public methods can use them.Typically, you use private member functions to handle implementation details that don’t form part of the public interface.
You don’t have to use the keyword private in class declarations because that is the default access control for class objects:
class World {
float mass; // private by default
char name[20]; // private by default
public:
void tellall(void);
...
};
1.2 Implementing Class Member Functions
待补充 529页
1.3 Using Classes
3 类的构造函数和析构函数
C++的目标之一是让使用类对象就像使用标准类型一样,但是常规的初始化语法不适用于类型Stock:

不能像上面这样初始化Stock对象的原因在于,数据部分的访问状态是私有的,这意味着程序不能直接访问数据成员。程序只能通过成员函数来访问数据成员,因此需要设计合适的成员函数,才能成功地将对象初始化(如果使数据成员成为公有,而不是私有,就可以按刚才介绍的方法初始化类对象,但使数据成为公有的违背了类的一个主要初衷:数据隐藏)。
一般来说,最好是在创建对象时对它进行初始化。例如:
Stock gift;
gift.buy(10,24.75);
就Stock类当前的实现而言,gift对象的company成员是没有值的。类设计假设用户在调用任何其他成员函数之前调用acquire(),但无法强加这种假设。避开这种问题的方法之一是在创建对象时,自动对它进行初始化。为此,C++提供了一个特殊的成员函数——类构造函数,专门用于构造新对象、将值赋给它们的数据成员。更准确地说,C++为这些成员函数提供了名称和使用语法,而程序员需要提供方法定义。名称与类名相同。例如,Stock类一个可能的构造函数是名为Stock()的成员函数。构造函数的原型和函数头有一个有趣的特征——虽然没有返回值,但没有被声明为void类型。实际上,构造函数没有声明类型。
3.1 声明和定义构造函数
待补充370
3.4 析构函数
用构造函数创建对象后,程序负责跟踪该对象,直到其过期为止。对象过期时,程序将自动调用一个特殊的成员函数——析构函数。 析构函数完成清理工作,因此实际上很有用。例如,如果构造函数使用new来分配内存,则析构函数将使用delete来释放这些内存。Stock 的构造函数没有使用new,因此析构函数实际上没有需要完成的任务。在这种情况下,只需让编译器生成一个什么要不做的隐式析构函数即可,Stock 类第一版正是这样 做的。然而,了解如何声明和定义析构函数是绝对必要的,下面为Stock类提供一个析构函数。
和构造函数一样,析构函数的名称也很特殊:在类名前加上~。因此,Stock 类的析构函数为~Stock()。另外,和构造函数一样,析构函数也可以没有返回值和声明类型。与构造函数不同的是,析构函数没有参数,因此Stock析构函数的原型必须是这样的:
~Stock();
由于Stock的析构函数不承担任何重要的工作,因此可以将它编写为不执行任何操作的函数:
Stock::~Stock(){}
什么时候应调用析构函数呢?这由编译器决定,通常不应在代码中显式地调用析构函数。如果创建的是静态存储类对象,则其析构函数将在程序结束时自动被调用。如果创建的是自动存储类对象(就像前面的示例中那样),则其析构函数将在程序执行完代码块时(该对象是在其中定义的)自动被调用。如果对象是通过new创建的,则它将驻留在栈内存或自由存储区中,当使用delete 来释放内存时,其析构函数将自动被调用。最后,程序可以创建临时对象来完成特定的操作,在这种情况下,程序将在结束对该对象的使用时自动调用其析构函数。
由于在类对象过期时析构函数将自动被调用,因此必须有一个析构函数。如果程序员没有提供析构函数,编译器将隐式地声明一个默认析构函数,并在发现导致对象被删除的代码后,提供默认析构函数的定义。
本文介绍了C++中的面向对象编程(OOP)及其关键特性,如抽象、封装、继承与数据隐藏。重点讲解了如何通过Stock类实现数据抽象,包括类声明、接口设计、访问控制及构造与析构函数。通过实例展示了如何创建和使用类,强调了数据隐藏和封装的重要性。
75万+

被折叠的 条评论
为什么被折叠?



