【抽象和类】

引言:生活中充满复杂性,处理复杂性的方法之一是简化和抽象。如果我们要用信息与用户之间的的接口来表示计算,那么抽象将是至关重要的。也就是说,将问题的本质特征抽象出来,并根据特征来描述解决方案。在上一讲的垒球统计数据示例中,接口描述了用户如何初始化、更新和显示数据。抽象是通往用户定义类型的捷径,在C++中,用户定义类型指的是实现抽奖接口的类设计。

1.1  类型是什么

  当我们看到一个给定的基本数据类型,我们会想到:

  • 它定义的数据对象需要的内存;
  • 它定义的数据对象能执行的操作;
  • 它决定如何解释内存中的位(如long和float在内存中占用的位数相同,但将它们转换为数值的方法不同)。

  具体来说,我们可以根据数据在内存中如何存储来考虑其数据类型(例如,char占用1个字节的内存,而double占用8个字节的内存),也可以根据能对数据进行的操作来定义其数据类型(例如,int类型可以使用所有的算术运算,可对整数执行加、减、乘、除运算,而且还可以对它们使用求模运算符%)。而指针需要的内存数量很可能与int相同,甚至可能在内部被表示为整数,但不能对指针执行与整数相同的运算(例如,不能将两个指针相乘,这种运算将毫无意义)。因此,将变量声明为int或float指针时,不仅仅是分配内存,还规定了可对变量执行的操作。

  对于内置类型来说,有关操作的信息被内置到编译器中。但在C++中定义用户自定义的类型时,必须自己提供这些信息。付出这些劳动换来了根据实际需要定制新数据类型的强大功能和灵活性。

1.2  C++中的类

  我们来尝试定义一个类:

  • 类声明:数据成员+成员函数(前者描述数据部分,后者描述公有接口)
  • 类方法定义:描述如何实现类成员函数

  我们仿佛感觉出:类声明提供了类的蓝图,而方法定义则提供了细节。

  什么是接口?

  接口是一个共享框架,供两个系统(如计算机和打印机之间或者用户和计算机程序之间)交互时使用。我们举一个例子:假设用户是我,程序是字处理器。我使用字处理器时,不能直接将脑子中想到的词传输到计算机内存中,而必须同程序提供的接口交互。我敲打键盘时,计算机将字符显示到屏幕上;我移动鼠标时,计算机移动屏幕上的光标,我无意间单击鼠标时,计算机对我输入的段落进行奇怪的处理。程序接口的意图转换为存储在计算机中的具体信息。

  对于类,我们常谈公共接口。在这里,公众(public)是使用类的程序,交互系统由类对象组成,而接口由编写类的人提供的方法组成。接口让程序员能够编写与类对象交互的代码,从而让程序能够使用类对象。举个例子:要计算string对象中包含多少个字符,我们无需打开对象,而只需使用string类提供的size()方法。类设计禁止公共用户直接访问类,但公众可以使用方法size()。方法size()是用户和string类对象之间的公共接口的组成部分。通常,方法getline()是istream类的公共接口的组成部分,使用cin的程序不是直接与cin对象内部交互来读取一行输入,而是使用getline()。

  如果希望更人性化,我们不要将使用类的程序视为公共用户,而将编写程序的人视为公共用户。然而,要使用某个类,必须了解其公共接口;要编写类,必须创建其公共接口。

  我们编程实现类时,通常将接口(类定义)放在头文件中,并将实现(类方法的代码)放在源代码文件中。在头文件中,对于数据成员,我们要进行定义,而对于成员函数,我们可以进行定义,也可以用原型表示(那这部分成员函数将在源代码文件中定义)。因此,对于描述函数接口而言,原型就够了。

  下面我们看一个头文件,它是Stock类的类声明:

// stock00.h -- Stock class interface
// version 00
#ifndef STOCK00_H_            //使用#ifndef访问多次包含同一个文件 
#define STOCK00_H_

#include <string>  

class Stock                  // class declaration
{
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();
};    // note semicolon at the end

#endif
stock00.h

相关文章: