什么是类(无师自通)

C++ 中,类是主要用于创建对象的构造体。在创建和使用对象之前,必须描述它将具有哪些成员变量和成员函数,这是通过定义一个类来完成的。

类(Class)是一种程序员定义的数据类型,用于描述从类创建的对象在构造时将是什么样子的。很快本节将介绍如何定义自己的类,但现在不妨先来看一下已经熟悉的类。

使用已经知道的类

教程几乎从一开始就一直在使用 string 类来创建和使用 string 对象。回想一下,在使用 string 类的任何程序中都必须具有以下 #include 指令:

#include <string>

这是必要的,因为 string 头文件是定义 string 类的地方。程序中包含此头文件,就可以根据需要定义多个 string 对象。其方法也很简单,只需命名该类,然后再输入想赋予对象的名字。示例如下。

string city, state;

该语句创建了两个 string 对象。一个被命名为 city,另一个被命名为 state。两个对象都是 string 类的实例,尽管它们可以赋给不同的数据值,但两个对象基本上看起来都一样。也就是说,两者都将有一个可以容纳一个字符串的成员变量,并且两者都具有可以对字符串操作的相同的一组函数。

一旦创建了一个 string 对象,就可以在其中存储数据。因为 string 类被设计为与赋值运算符一起使用,所以可以为 string 对象赋值字符串常数,示例如下:

city= "Chicago";
state = "Illinois";

这些语句将 Chicago 存储在 city 对象的成员变量中,将 Illinois 存储在 state 对象的成员变量中。

string 类包括许多成员函数,它们可以对 string 对象所持有的数据执行操作。在教程前面的章节中,曾经介绍了其中的几个。其中一个是名为 length 的成员函数,它返回 string 对象中存储的字符串的长度。示例如下:

cout << city.length () << endl; // 该语句打印 7
cout << state.length () << endl; // 该语句打印 8

这些语句都调用了相同的成员函数,但在每种情况下都可以使用对象自己的数据。存储在 city 中的数据是长度为 7 的字符串,而存储在 state 中的数据则是长度为 8 的字符串。

需要再次强调的是,创建和使用 string 对象,并不需要知道如何实现 string 类,只需要知道它可以保存什么类型的数据,以及可以调用哪些函数对数据进行操作。

创建自己的类

要创建自己的类,必须编写一个类的声明。以下是类声明的一般格式:

class ClassName //类声明以关键字class和类名称开始
{
    //在这里声明类的成员变量和成员函数
}; //注意,这里需要分号

现在来通过一个示例一步一步地学习如何实现类。

Circle对象包含一个成员变量和两个成员函数
图 1 Circle 对象包含一个成员变量和两个成员函数
 
例如创建图 1 中所示的简单 Circle 类。第一步是确定类应具有的成员变量和成员函数。在图中可以确定,类需要一个成员变量来保存圆的半径和两个成员函数:setRadius 和 getArea。

注意,这些信息以及其他设计信息有时也是使用可视化建模工具来表示的,该工具是面向对象建模“语言”的一部分,该语言被称为统一建模语言(UML)。图 1 演示了一种常用的 UML 图,称为类图

类设计完成后,下一步是编写类声明。它将告诉编译器该类包括什么内容。以下是 Circle 类的声明:
class Circle
{
    private:
        double radius;
    public:
        void setRadius(double r)
        {
            radius = r;
        }
        double getArea()
        {
            return 3.14 * pow(radius,2);
        }
}
请注意,类名以大写字母开头。虽然这并不是严格要求的,但是习惯上应始终使用大写字母开始类名。

访问修饰符

类声明非常类似于图 1,其中添加了每个成员函数的实际代码以及两个关键字:privatepublic。这两个关键字称为访问修饰符,因为它们指定谁可以访问类的各个成员。

请注意,每个访问修饰符后面都有一个冒号。公共成员变量可以由类外的函数访问,公共成员函数可以由类外的函数调用。另一方面,私有(private)成员变量只能由作为同一个类的成员的函数访问,私有成员函数只能由作为该类成员的其他函数调用。如果完全省略了 public 和 private 关键字的话,则一切都将默认为私有的,这样做并不实用,因为这样的话,除了在特殊情况下,否则类之外的任何函数都不能使用该类。

在 Circle 类示例中,成员变量 radius 被声明为 private,成员函数被声明为 public。这是很常见的。成员数据通常被设为私有,以对它进行保护。然后创建公共函数,以便允许类外代码进行严密控制的数据访问。现在可以将示例中所有的类成员变量都声明为 private,所有的成员函数都声明为 public。稍后将会看到使用私有成员函数的情况。

注意,如果类之外的程序语句尝试访问私有成员,将导致编译器错误。

private和public成员的位置

是先列出私有成员还是先列出公共成员无关紧要。实际上,甚至不要求同一个访问修饰符的所有成员一起声明。以下两个示例都是 Circle 类的合法声明:
//示例1
class Circle
{
    public:
        void setRadius(double r)
        {
            radius = r;
        }
        double getArea()
        {
            return 3.14 * pow(radius, 2);
        }
        private:
            double radius;
};
//示例2
class Circle
{
    public:
        void setRadius(double r)
        {
            radius = r;
        }
    private:
        double radius;
    public:
        double getArea()
        {
            return 3.14 * pow (radius, 2);
        }
};
大多数程序员认为应该更有秩序地分开私有和公共成员,而且绝大多数的教师也提倡这样做。教程中遵循首先列出私有成员的标准做法,然后才是公共成员。