StupidBeauty
Read times:3219Posted at:Wed Jun 21 13:31:16 2017 - no title specified

《C++面向对象软件设计及构建》文章翻译:2.2类及对象的结构,2.2 Structure of Classes and Objects

要想使用已有类的对象,就有必要理解它们的结构及操作方式。这跟开车是一样的,学习开车时,有必要理解车子的结构 - 驾驶员坐在哪里,点火钥匙插在哪里 - 以及车子的操作方式 - 方向盘起什么作用,加速踏板起什么作用,等等。

公有部分和私有部分

对于程序猿来说,要想(重复)使用某个已有的类,在该个类中的关键元素是它的 公有接口 。类的公有接口,定义了所有利用这个类的定义而创建的对象的行为。公有接口中,包含了一组方法(也被称作过程、成员函数或操作),这些方法可用来对以这个类为范本创建的对象进行操作。对一个对象进行操作的唯一手段,就是,使用这个对象所属的类的公有接口中定义的方法。

在类中,以及由这个类创建的任何对象中,都还包含着一个私有的(隐藏的、内部的、封装起来的)实现。对象的使用者完全不知道对象是如何实现的,类比于汽车来说,驾驶员完全不知道汽车的发动机是如何构造的。对象的实现中的内部细节,可被对象的用户忽略。

在C++中,类的公有部分和私有部分,是由关键字来区分的,如下所示:

class Frame {

private:

// 封装起来 的实现,位于此处

public:

// 公有接口,位于此处

};

将公有接口与私有实现分割开,这是面向对象编程的一个重要特点。公有接口,在对象的实现者和对象的使用者之间达到一个约定。这个约定,指明了,实现者承诺了提供什么样的服务,同时限制了使用者该如何使用这个对象。

将公有接口与私有实现分割开来,这种做法,有多种好处:

  • •.它提升了理解程度和复用程度,因为,它减少了对象的用户需要关注的信息量

  • •. 它提升了实现上的灵活性,因为,实现者可以在日后改变具体的实现方式(例如改成某个更高效的实现方式),而该对象仍然在其使用者面前保持相同的外观且维持相同的行为,用户并不知道具体的实现已经改变了,

  • •.它降低了调试的难度,因为,它划出了一个边界,可用于分割具体错误所发生的源头

  • •.它提升了整个系统的设计效果,因为,可通过一组公有接口的方式来呈现及理解系统

随着对于面向对象编程概念的深入了解,随着构建面向对象系统的工作过程中经验的积累,妳将会更加深刻地认识到以上好处。

公有接口中的方法

公有接口中,可能(通常就是这样)包含三种不同类型的方法:

  • •.构造函数:这些方法,定义的是,对象如何初始化。通常会有多种构造函数,使得对象能够以不同的方式来初始化。当对象被创建时,构造函数会被隐式调用。在不调用构造函数的情况下,无法创建对象。

  • •.析构函数:每个类中,这种函数只会有一个,当对象被销毁时,会隐式调用这个函数。

  • •.行为方法:这些方法,定义的是,在对象的生命周期中,会做出何种行为,或者说,能够被怎样操作。这些方法,通常又能够细分成以下类型:

    • •.访问函数/查询函数,它们返回对象的状态相关的信息,但不会改变对象的状态。和

    • •.操作函数/变动函数,它们(潜在)改变对象的状态。

如果未定义构造函数或析构函数,则会提供一个默认的实现。默认的构造函数和默认的析构函数什么事都不做。

注意,构造函数和析构函数都是被隐式调用的。也就是说,它们会随着某种指令的执行而被自动调用。例如,当某个已声明的对象被创建时,就会有某个构造函数被隐式调用;构造函数因为这里的声明语句而被调用。构造函数和析构函数无法被程序猿的代码来显式调用。

对于图形用户界面窗口的抽象

Frame 类,是对于图形用户界面(GUI)窗口 的多个 抽象 中的第一个。图形用户界面 的窗口,有多种能力,如下所示。实际使用 中的图形用户界面窗口,功能强大:它拥有多种操作, 可用于改变它的位置和尺寸; 它能够显示多种用于信息提供用途的元素 (图形 化的、图标式的、文字式的 ) ;提供 了一些手段,让用户可通过控制元素(按钮 、菜单,等等 )来与之交互。 为了避免在学习过程中的第一课就面对这么多的强大功能, 我们会搞出一系列较简单的抽象 ,如下所示 。下 图展示了其中的第一个较简单抽象。

对图形用户界面窗口的抽象

联想到之前所说的,将抽象成果映射到具体类上的概念,就可以写出Frame 类的第一个版本的定义了,如下所示。

Frame

class Frame {                   // 版本1

 private:

          // 封装起来的数据位于这里

 public:

        Frame      (char *name, int initXCoord, int initYCoord,

                                int initWidth,  int initHeight);

   void Resize     (int newHeight, int newWidth  );

   void MoveTo     (int newXCoord, int newYCoord );

   int  IsNamed    (char *name);

   void Clear      ();

   void DrawText   (char *text, int atX, int atY);

   void DrawLine   (int fromX, int fromY, int toX, int toY);

   void DrawCircle (int centerX, int centerY, int radius);

       ~Frame   ();

};

在这个示例中,构造函数的名字,与类的名字(Frame)相同。这个构造函数需要5个参数:要与这个Frame 相关联的名字;这个Frame 的左上角的初始(x,y)坐标,以一对整数(initXCoord, initYCoord)的方式来传递;以及,这个Frame 的初始大小(宽度和高度)。最后一个方法,~Frame,即为析构函数;此处放置的是,当该Frame 对象被销毁时,必须执行的那些动作。IsNamed方法,是一个访问函数,用来让程序猿检查,Frame 的名字是否与该方法中传入的参数一 致。其它的方法都是操作方法。Resize 和MoveTo 这两个方法,提供的操作,可用于将Frame 移动到屏幕上新的位置,以及改变它的大小。DrawLine 和DrawCircle 两个方法,可用于在Frame 中绘制简单的图形形状。DrawText方法,可用来将文字内容显示到Frame 中去。(atX, atY)两个坐标参数,指定的是,要将文字内容的左上角放置在Frame 中的什么位置。Clear方法,会从 Frame 中擦除所有的文字内容和图形内容。实际使用中的Frame 类,会有更多的方法,不过,此处列举的这些,就足以实现多个有趣的示例了。

注意,在上面列出的Frame 类的定义中,未给出其中任何方法的实际可执行代码。这样做,是为了隐藏掉对象的所有的实现细节 - 类的用户,只需要关注它定义了哪些操作,无需关注这些操作具体是如何实现的。当然,这个类的创造者,必须为这些方法编写实际的代码,并且提供其它的私有数据。我们日后再研究其具体做法。

1 任务

  1. 1. 为“整数组成的栈”这个类编写一个类定义(不包含私有部分)。

  2. 2. 为“人物档案”这个类编写一个类定义(不包含私有部分)。

  3. 3. 为Frame 类(版本1)编写一个变种, 它能够按照相对数量来移动这个Frame(也就是说,向上或向下移动指定的坐标单位,以及向左或向右移动指定的坐标单位)。

  4. 4. 为Frame 类(版本1)编写一个变种,它能够按照指定的比例来改变这个Frame 的大小(例如,让它增大50%,或减小50%)。

  5. 5. 为Frame 类(版本1)编写一个变种,它能够Frame 向中绘制矩形和三角形。

赤裸特工

未知美人

Your opinions
Your name:Email:Website url:Opinion content:
- no title specified

HxLauncher: Launch Android applications by voice commands