友情提示:如果本网页打开太慢或显示不完整,请尝试鼠标右键“刷新”本网页!
第三电子书 返回本书目录 加入书签 我的书架 我的书签 TXT全本下载 『收藏到我的浏览器』

深入浅出MFC第2版(PDF格式)-第19部分

快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部! 如果本书没有阅读完,想下次继续接着阅读,可使用上方 "收藏到我的浏览器" 功能 和 "加入书签" 功能!


                    【            】。如果你选择                      ( 1…9a),你会看到执行线程             (优 



                                                            1                             2 

                   先权最高)几乎一路冲到底,然后才是执行线程                      (优先权次之),然后是执行线程 (优 



                              。。。              ! §sleep delay! ¨  图 

                   先权再次之)  。但如果你选择的                          ( 1…9b),所有执行线程不分优先权高 



                   低,同时行动。关于执行线程的排程问题,我将在第14 章做更多的讨论。 



                   图                  的执行画面 ( ! ¨               ! ¨ ) 

                     1…9a Mlt iTh rd 。exe          fo r  lo o p  d e la y 



                    图                 的执行画面 ( ! ¨              ! ¨ ) 

                      1…9b Mlt iTh rd 。exe          s le e p  d e la y 



                              图               1                 2~4                      CPU 

                  注意:为什么        1…9a 中执行线程 尚未完成,执行线程                竟然也有机会偷得一点点              时 



                  间呢?这是排程器的巧妙设计,动态调整执行线程的优先权。是啊,总不能让优先权低的 



                  执行线程直到天荒地老,没有一点点获得。关于执行线程排程问题,第14章有更多的讨论。 



52 


…………………………………………………………Page 115……………………………………………………………

 图        Process Viewer Visual C++ 5。0       Mltithrd。exe  

   1…10 是以            (           所附工具)观察              的执行结果。 



 图上方出现目前所有的进程,点选其中的MLTITHRD。EXE ,果然在窗口下方出现六个执 



 行线程,其中包括主执行线程(优先权已被调整为10)。 



图     利用               (           )观察 

  1…10   Proces s Viewe r PVIEW95。EXE   MLTITHRD。EXE 



      的执行, 的确发现有六个执行线程, 其中包括一个主执行线程。 

                                    



                                                                          53 


…………………………………………………………Page 116……………………………………………………………

        54 


…………………………………………………………Page 117……………………………………………………………

第 2章 



             C++ 的重要性质 



            C++ 是一种扭转程序员思维模式的语言。 



        一个人思维模式的扭转,不可能轻而易举一蹴而成。 



 迩来「对象导向」一词席卷了整个软件界。对象导向程序设计(Object Oriented 



 Programming )其实是一种观念,用什么语言实现它都可以。但,当然,对象导向程序语 



 言(Object Oriented Programming Language )是专门为对象导向观念而发展出来的,以之 



 完成对象导向的封装、继承、多态等特性自是最为便利。 



 C++                       C           C  

    是最重要的对象导向语言,因为它站在  语言的肩膀上,而  语言拥有绝对优势 



 的使用者。C++ 并非纯然的对象导向程序语言,不过有时候混血并不是坏事,纯种也不 



 见得就多好。 



 所谓纯对象导向语言,是指不管什么东西,都应该存在于对象之中。JAVA 和Small Talk 



 都是纯对象导向语言。 



 如果你是C++  的初学者,本章不适合你(事实上整本书都不适合你),你的当务之急 



 是去买一本C++ 专书。一位专精Basic 和Assembly 语言的朋友问我,有没有可能不 



 会C++ 而学会MFC ?答案是当然没有可能。 



 如果你对C++ 一知半解,语法大约都懂了,语意大约都不懂,本章是我能够给你的最 



 好礼物。我将从类别与对象的关系开始,逐步解释封装、继承、多态、虚拟函数、动态 



 绑定。不只解释其操作方式,更要点出其意义与应用,也就是,为什么需要这些性质。 



                                                           55 


…………………………………………………………Page 118……………………………………………………………

    C++ 语言范围何其广大,这一章的主题挑选完全是以MFC Programming 所需技术为前 



    提。下一章,我们就把这里学到的C++ 技术和OO 观念应用到application framework  的 



    仿真上,那是一个DOS 程序,不牵扯Windows 。 



类别及其成员 谈封装 (                                     ) 

                              encapsulation 



    让我们把世界看成是一个由对象(object )所组成的大环境。对象是什么?白一点说,「东 



    西」是也!任何实际的物体你都可以说它是对象。为了描述对象,我们应该先把对象的 



    属性描述出来。好,给「对象的属性」一个比较学术的名词,就是「类别」(class )。 



    对象的属性有两大成员,一是资料,一是行为。在对象导向的术语中,前者常被称为 



    property Java        field             method 

           (   语言则称之为        ),后者常被称为           。另有一双比较像程序设计 



                  member variable data member member function 

    领域的术语,名为                  (或          )和              。为求统一,本 



                         member variable         member function 

    书使用第二组术语,也就是                     (成员变量)和                  (成员函数)。 



    一般而言,成员变量通常由成员函数处理之。 



    如果我以CSquare 代表「四方形」这种类别,四方形有color,四方形可以displ ay 。好, 



    color 就是一种成员变量,displ ay 就是一种成员函数: 



        CSquare square; // 声明square 是一个四方形。 



        square。color = RED; // 设定成员变量。RED 代表一个颜色值。 



        square。display (); // 调用成员函数。 



    下面是C++ 语言对于CSquare  的描述: 



        class CSquare // 常常我们以C 作为类别名称的开头 



        { 



        private: 



            int m_color; // 通常我们以m_ 作为成员变量的名称开头 



        public: 



            void display () {  。。。 } 



            void setcolor (int color) { m_color = color; } 



        }; 



    成员变量可以只在类别内被处理,也可以开放给外界处理。以资料封装的目的而言,自 



                                                                             56 


…………………………………………………………Page 119……………………………………………………………

                                               C++      pr ivate publ ic  

    然是前者较为妥当,但有时候也不得不开放。为此,                       提供了        、      和 



    pr otected                                pr ivate 

            三种修饰词。一般而言成员变量尽量声明为                     ,成员函数则通常声明为 



    publ ic     m_color         pr ivate                       setcolor 

         。上例的          既然声明为         ,我们势必得准备一个成员函数                  , 



    供外界设定颜色用。 



               pr ivate 

    把资料声明为           ,不允许外界随意存取,只能透过特定的接口来操作,这就是对象 



    导向的封装(encapsulation )特性。 



基础类别与衍生类别 :谈继承(Inheritance) 



                                     C              struct 

    其它语言欲完成封装性质,并不太难。以  为例,在结构(                         )之中放置资料,以 



    及处理资料的函数的指针(function pointer ),就可得到某种程度的封装精神。 



    C++ 神秘而特有的性质其实在于继承。 



    矩形是形,椭圆形是形,三角形也是形。苍蝇是昆虫,蜜蜂是昆虫,蚂蚁也是昆虫。是 



    的,人类习惯把相同的性质抽取出来,成立一个基础类别(base class ),再从中衍化出 



    衍生类别(derived class )。所以,关于形状,我们就有了这样的类别阶层: 



                            Shape 

                            Shape 



          Ellipse          Triangle         Rectangle 

           Ellipse          Triangle         Rectangle 



           Circle                            Square 

            Circle                            Square 



    注意:衍生类别与基础类别的关系是“IsKindOf” 的关系。也就是说, 



          「是一种」         ,       「是一种」         ; 

    Circle        Ellipse Ellipse       Shape 



           「是一种」            ,          「是一种」         。 

    Square         Rectangle  Rectangle        Shape 



                                                                                    57 


…………………………………………………………Page 120……………………………………………………………

                   #0001  class CShape        // 形状 

                   #0002  { 

                   #0003  private: 

                   #0004    int m_color; 

                   #0005 

                   #0006  public: 

                   #0007    void setcolor(int color) { m_color = color; } 

                   #0008  }; 

                   #0009 

                   #0010  class CRect : public CShape         // 矩形是一种形状 

                   #0011  {                                    // 它会继承 m_color 和 setcolor() 

                   #0012  public: 

                   #0013    void display() { 。。。 } 

                   #0014  }; 

                   #0015 

                   #0016  class CEllipse : public CShape    // 椭圆形是一种形状 

                   #0017  {                                    // 它会继承 m_color 和 setcolor() 

                   #0018  public: 

                   #0019    void display() { 。。。 } 

                   #0020  }; 

                   #0021 

                   #0022  class CTriangle : public CShape   // 三角形是一种形状 

                   #0023  {                                      // 它会继承 m_color 和 setcolor() 

                   #0024  public: 

                   #0025    void display() { 。。。 } 

                   #0026  }; 

                   #0027 

                   #0028  class CSquare : public CRect      // 四方形是一种矩形 

                   #0029 

                   #0030  public: 

                   #0031    void display() { 。。。 } 

                   #0032  }; 

                   #0033 

                   #0034  class CCircle : public CEllipse   // 圆形是一种椭圆形 

                   #0035  { 

                   #0036  public: 

                   #0037    void display() { 。。。 } 

                   #0038  }; 



                   于是你可以这么动作: 



                   CSquare square; 

                   CRect   rect1; rect2; 

                   CCircle circle; 



                     square。setcolor(1);   // 令 square。m_color = 1; 



58 


…………………………………………………………Page 121……………………………………………………………

     square。display (); // 调用CSquare::display 



     rect1。setcolor (2); // 于是rect1。m_color = 2 



     rect1。display (); // 调用CRect::display 



     rect2。setcolor (3); // 于是rect2。m_color = 3 



     rect2。display (); // 调用CRect::display 



     circle。setcolor (4); // 于是circle。m_color = 4 



     circle。display (); // 调用CCircle::display 



 注意以下这些事实与问题: 



 1。 所有类别都由CShape 衍生下来,所以它们都自然而然继承了CShape  的成员, 



   包括变量和函数。也就是说,所有的形状类别都「暗自」具备了m_color 变量 



   和setcolor  函数。我所谓暗自(implicit ),意思是无法从各衍生类别的声明中 



   直接看出来。 



 2。 两个矩形对象rect1 和rect2 各有自己的m_color,但关于setcolor  函数却是 



            CRect::setcolor             CShape::setcolor 

   共享相同的                 (其实更应该说是                    )。我用这张图表 



   示其间的关系: 



                                       这个this 参数是编译器自行为我们加上的, 

                                                   “       ” 

        对象rect1        
返回目录 上一页 下一页 回到顶部 0 0
快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部!
温馨提示: 温看小说的同时发表评论,说出自己的看法和其它小伙伴们分享也不错哦!发表书评还可以获得积分和经验奖励,认真写原创书评 被采纳为精评可以获得大量金币、积分和经验奖励哦!