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

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

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


                                                   “       ” 

        对象rect1         对象rect2        所以我说它是个 隐藏指针 。 



                                        CRect::setcolor(int color; 

       m_color         m_color 

                                                       CRect* this) 

                                        { 

                                         this…》m_color = color; 

                                        } 



         this 指针       this 指针 



     rect1。setcolor   rect2。setcolor            CRect::setcolor 

                     和                 调用的都是                    , 

     后者之所以能分别处理不同对象的成员变量,完全是靠一个隐藏的this 指针。 



                                                     rect1 setcolor  

让我替你问一个问题:同一个函数如何处理不同的资料?为什么                             。      和 



rect2 setcolor        CRect setcolor         CShape  setcolor 

    。      明明都是调用          ::      (其实也就是          ::      ),却能够 



                 rect1 m_color  rect2。m_color           this  

有条不紊地分别处理            。      和            ?答案在于所谓的          指针。下 



一节我就会提到它。 



                                                                                   59 


…………………………………………………………Page 122……………………………………………………………

3。  既然所有类别都有displ ay 动作,把它提升到老祖宗CShape 去,然后再继承 



  之,好吗?不好,因为displ ay  函数应该因不同的形状而动作不同。 



     displ ay                               f or    while 

4。 如果      不能提升到基础类别去,我们就不能够以一个                循环或 



  循环干净漂亮地完成下列动作(此种动作模式在对象导向程序方法中重要无 



  比): 



     CShape shapes'5'; 



      。。。 //   5   shapes  

            令  个       各为矩形、四方形、椭圆形、圆形、三角形 



     for  (int i=0; im_color = color; } 



          }; 



    我们拨开了第一道疑云。 



                                                                                      61 


…………………………………………………………Page 124……………………………………………………………

              虚拟函数与多态(Polymorphism) 



                  我曾经说过,前一个例子没有办法完成这样的动作: 



                      CShape shapes'5'; 



                      。。。 //   5   shapes  

                             令  个       各为矩形、四方形、椭圆形、圆形、三角形 



                      for  (int i=0; idisplay(); 



                 Ellipse   Square  Triangle  Rect    Circle   Square   Circle   Circle 



                  为了支持这种能力,C++ 提供了所谓的虚拟函数(virtual function )。 



                     +    ?!  

                  虚拟  函数    听起来很恐怖的样子。如果你了解汽车的离合器踩下去代表汽车空档, 



                  空档表示失去引擎本身的牵制力,你就会了解「高速行驶间煞车绝不能踩离合器」的道 



                  理并矢志遵行。好,如果你真的了解为什么需要虚拟函数以及什么情况下需要它,你就 



                  能够掌握它的灵魂与内涵,真正了解它的设计原理,并且发现认为它非常人性。并且, 



                  真正知道怎么用它。 



62 


…………………………………………………………Page 125……………………………………………………………

让我用另一个例子来展开我的说明。这个范例灵感得自Visual C++ 手册之一: 



Introdoction to C++。假设你的类别种类如下: 



                                                   CEmployee 

                                                    CEmployee 



                                          CManager              CWage 

                                           CManager              CWage 



                                                                CSales 

                                                                 CSales 



本图以Visual C++ 之「Class Info 窗口」获得 



程序代码实作如下: 



#0001  #include  

#0002 

#0003  //……………………………………………………………………………………………………………………………………………………………………

#0004  class CEmployee   // 职员 

#0005  { 

#0006  private: 

#0007  char m_name'30'; 

#0008 

#0009  public: 

#0010    CEmployee(); 

#0011    CEmployee(const char* nm) { strcpy(m_name; nm); } 

#0012  }; 



                                                                                    63 


…………………………………………………………Page 126……………………………………………………………

                  #0013  //……………………………………………………………………………………………………………………………………………………………………

                  #0014  class CWage : public CEmployee      // 时薪职员是一种职员 

                  #0015  { 

                  #0016  private : 

                  #0017    float m_wage; 

                  #0018    float m_hours; 

                  #0019 

                  #0020  public : 

                  #0021    CWage(const char* nm)  : CEmployee(nm) { m_wage = 250。0; m_hours = 40。0; } 

                  #0022    void setWage(float wg)  { m_wage = wg; } 

                  #0023    void setHours(float hrs)  { m_hours = hrs; } 

                  #0024    float putePay(); 

                  #0025  }; 

                  #0026  //……………………………………………………………………………………………………………………………………………………………………

                  #0027  class CSales : public CWage     // 销售员是一种时薪职员 

                  #0028  { 

                  #0029  private : 

                  #0030    float m_m; 

                  #0031    float m_sale; 

                  #0032 

                  #0033  public : 

                  #0034    CSales(const char* nm) : CWage(nm)  { m_m = m_sale = 0。0; } 

                  #0035    void setmission(float m)      { m_m = m; } 

                  #0036    void setSales(float sale)           { m_sale = sale; } 

                  #0037    float putePay(); 

                  #0038  }; 

                  #0039  //……………………………………………………………………………………………………………………………………………………………………

                  #0040  class CManager : public CEmployee   // 经理也是一种职员 

                  #0041  { 

                  #0042  private : 

                  #0043    float m_salary; 

                  #0044  public : 

                  #0045    CManager(const char* nm) : CEmployee(nm)  { m_salary = 15000。0; } 

                  #0046    void setSalary(float salary)              { m_salary = salary; } 

                  #0047    float putePay(); 

                  #0048  }; 

                  #0049  //……………………………………………………………………………………………………………………………………………………………………

                  #0050  void main () 

                  #0051  { 

                  #0052  CManager aManager(〃陈美静〃); 

                  #0053  CSales   aSales(〃侯俊杰〃); 

                  #0054  CWage    aWager(〃曾铭源〃); 

                  #0055  } 

                  #0056  //……………………………………………………………………………………………………………………………………………………………………

                  #0057  // 虽然各类別的 putePay 函数都没有定义,但因为程序也没有调用之,所以无妨。 



64 


…………………………………………………………Page 127……………………………………………………………

如此一来,CWage 继承了CEmpl oyee 所有的成员(包括资料与函数),CSales 又继承 



了CWage 所有的成员(包括资料与函数)。在意义上, 相当于CSales 拥有资料如下: 



    // private data of CEmployee 

   char m_name'30'; 



    // private data of CWage 

   float m_wage; 

   float m_hours; 



    // private data of CSales 

   float m_m; 

   float m_sale; 



 以及函数如下: 



   void setWage(float wg); 

   void setHours(float hrs); 

   void setmission(float m); 

   void setSale(float sales); 

   void putePay(); 



  从Visual C++  的除错器中,我们可以看到,上例的main 执行之后,程序拥有三个对象, 



  内容(我是指成员变量)分别为: 



                                                                                 65 


…………………………………………………………Page 128……………………………………………………………

从薪水说起 



    虚拟函数的故事要从薪水的计算说起。根据不同职员的计薪方式,我设计put ePay  函 



    数如下: 



       float CManager::putePay () 



        { 



            return m_salary; // 经理以「固定周薪」计薪。 



        } 



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