《C++ Primer Plus》第十章 对象和类 Shepard-Wang

一 类的设计

步骤:

  1. 提供类声明

    class className
    {
      private:
        data member declarations;
      public:
    	member function prototypes;
    };
    
  2. 实现类成员函数

    假设有一个加 Bozo 的类,有一个成员函数 Retort()

    char* Bozo::Retort()
    {
        ...
    }
    

二 构造和析构

当程序创建未被显式初始化的类对象时,总是调用默认构造函数

程序练习

const 成员函数

const Stock land("Shepard");
land.show();

对于现在的 C++ 来说,编译器拒绝第二行。

因为 show() 的代码无法确保调用的对象不被修改。

将声明和定义修改为:

void show() const; // promise not to change invoking object

void stock::show() cosnt;

就像尽可能使用 const 引用和指针用作函数形参一样,只要类方法不修改调用对象,就应该将其声明为 const

构造与析构小结

通常,构造函数用于初始化类对象的成员,初始化应与构造函数的参数列表匹配。例如,类 Bozo 的构造函数的原型如下:

Bozo(const char* fname, const char* lname);

则可以用它来初始化新对象:

Bozo a = Bozo("Wang", "Shepard");		// primary form
Bozo b("Wang", "Shepard");				// short form
Bozo *pb = new Bozo("Wang", "Shepard"); // dynamic object

如果 构造函数只有一个参数 ,则将对象初始化为一个与参数类型相同的值时,该构造函数会被调用。例如:有这样一个构造函数:

Bozo(int age);

则可以使用下面任意一种方式初始化对象:

Bozo a = Bozo(21);
Bozo b(21);
Bozo c = 21;		// special for one-argument constructors

默认构造函数

  • 无参
  • 全缺省
Bozo();
Bistro(const char* s = "Shepard");

三 this 指针

this 指针的类型

一般类型:类类型的 const 指针

被 const 修饰:const 类类型 const 指针

为前面的 stock 类添加比较两个价值的函数:

const Stock& Stock::topval(const Stock& s) const
{
    if(s.total_val > total_val)
        return s;
    else
        return *this;
}

四 对象数组

创建对象数组:

Stock mystuff[4]; // 4 个成员都调用默认构造函数
Stock stock[10] = {
  Stock("NanoSmart", 12.5, 20),
  Stock(),
  Stock("Shepard", 130, 12.5),
   // 后 7 个调用默认构造
};

初始化对象数组的方式 :首先使用默认构造函数创建数组元素,然后花括号中的构造函数先创建临时对象,然后将临时对象的内容复制到相应的元素中。

但是编译器可能会优化,直接使用花括号中构造函数的参数构造数组元素。

要创建对象数组,则这个类必须有默认构造函数

五 接口和实现

修改类的私有部分和实现文件属于 实现的变更 ;修改类的公有部分属于 接口变更 。实现变更改变了类的内部工作原理,接口变更改变了使用类的人可用的编码方式。

六 类作用域

类成员访问

在类中定义的名称(如类数据成员名和类函数成员名)的 作用域为整个类 ,作用域为整个类的名称只在该类中是已知的,在类外是不可知的。

在类外,构造函数名称在被直接调用时,才能被识别 ,因为它的名称与类名是相同。在其他情况下,使用类成员名时,必须根据上下文使用 直接成员操作符(.),间接成员操作符 (->) 或 作用域解析操作符::)。

作用域为整个类的常量

有时候,使符号常量的作用域为整个类很有用。另外,常量对于所有对象来说都是相同的,因此创建一个所有类共享的常量是个不错的主意(节省空间)。

注意下面的代码:

class Stock    
{
  private:
    const int Len = 30;
    char company[Len]; // Error
};

这是行不通的,因为声明类只是描述了对象的形式,并没有真正创建对象。因此,在对象被创建之前将没有用于存储值的空间。

<批注:数组大小需要在编译时确定,而 const 在运行时才会确定。 退一步来说,这种定义方式也不能实现多个类共享一个常量。>

有两种方式实现:

在类中声明一个枚举 类中的枚举作用域为整个类。

enum{ Len = 30 };
int array[Len];

这种方式声明的枚举并不会创建类数据成员。所有对象中不会包含枚举。编译器会用 30 替换 Len

<批注:const int Len 不能算真正从常量,它算“常变量”。C++ 标准中指出:整数常量表达式是整数或无范围的枚举类型>

使用 static

static const int Len = 30;
int array[Len];

该常量与其他静态变量存储在一起,而不是存储在类中。

参考资料

《C++ Primer Plus 5 edition》