• 【译】多态(二)


    抽象基类

    抽象基类很像我们之前例子的CPolygon类。唯一的区别是,之前的例子中我们为CPolygon类的对象(如poly)定义了一个具有最少功能的有效函数area(),而抽象基类中不能为area()成员函数提供任何实现。这通过在函数声明后加上“=0”实现。 

    一个抽象基类CPolygon可能像这样:

    // abstract class CPolygon 
    class CPolygon { 
      protected: 
        int width, height; 
      public: 
        void set_values (int a, int b) 
          { width=a; height=b; } 
        virtual int area () =0; 
    };
    

    注意到我们在virtual int area()后加了“=0”,代替此函数的实现。这种类型的函数称为纯虚函数,含有至少一个纯虚函数的类称为抽象基类。 

    抽象基类与普通多态类的主要区别在于,不能被实例化,因为在抽象基类中至少存在一个缺少实现的成员。 

    不过,一个不能实例化对象的类并不是全然无用。我们可以创建它的指针,并利用它的多态特性。因此,如下的声明:

    CPolygon poly;

    对于我们声明的抽象基类是无效的,因为试图实例化一个对象。不过,如下的指针:

    CPolygon * ppoly1;

    CPolygon * ppoly2;

    却是完全合法的。 

    至此,既然CPolygon包含一个纯虚函数,它就是一个抽象基类。不管怎样,这个抽象基类的指针可以用来指向其派生类的对象。 

    这里是完整的例子:

    // abstract base class 
    #include <iostream> 
    using namespace std; 
     
    class CPolygon { 
      protected: 
        int width, height; 
      public: 
        void set_values (int a, int b) 
          { width=a; height=b; } 
        virtual int area (void) =0; 
      }; 
     
    class CRectangle: public CPolygon { 
      public: 
        int area (void) 
          { return (width * height); } 
      }; 
     
    class CTriangle: public CPolygon { 
      public: 
        int area (void) 
          { return (width * height / 2); } 
      }; 
     
    int main () { 
      CRectangle rect; 
      CTriangle trgl; 
      CPolygon * ppoly1 = &rect; 
      CPolygon * ppoly2 = &trgl; 
      ppoly1->set_values (4,5); 
      ppoly2->set_values (4,5); 
      cout << ppoly1->area() << endl; 
      cout << ppoly2->area() << endl; 
      return 0; 
    }
    

    输出:20 10 

    如果重新审视一下这段程序,你会发现我们用同一类型的指针(CPolygon*)访问了不同的对象。这会非常有用。例如,现在我们为抽象基类CPolygon创建一个函数成员来在屏幕上打印area()的结果,尽管CPolygon类自己没有此函数的实现:

    // pure virtual members can be called 
    // from the abstract base class 
    #include <iostream> 
    using namespace std; 
     
    class CPolygon { 
      protected: 
        int width, height; 
      public: 
        void set_values (int a, int b) 
          { width=a; height=b; } 
        virtual int area (void) =0; 
        void printarea (void) 
          { cout << this.>area() << endl; } 
      }; 
     
    class CRectangle: public CPolygon { 
      public: 
        int area (void) 
          { return (width * height); } 
      }; 
     
    class CTriangle: public CPolygon { 
      public: 
        int area (void) 
          { return (width * height / 2); } 
      }; 
     
    int main () { 
      CRectangle rect; 
      CTriangle trgl; 
      CPolygon * ppoly1 = &rect; 
      CPolygon * ppoly2 = &trgl; 
      ppoly1->set_values (4,5); 
      ppoly2->set_values (4,5); 
      ppoly1->printarea(); 
      ppoly2->printarea(); 
      return 0; 
    }
    

    输出:20 10

    虚成员和抽象基类赋予了C++多态特性,这使得面向对象的编程方法对大型工程来说是如此有用。当然,我们已经看到了这些特性的非常简单的应用,但是这些特性可以用在对象数组或动态创建的对象上。

    我们再次以同样的例子结尾,但这次对象是动态创建的: 

    // dynamic allocation and polymorphism 
    #include <iostream> 
    using namespace std; 
     
    class CPolygon { 
      protected: 
        int width, height; 
      public: 
        void set_values (int a, int b) 
          { width=a; height=b; } 
        virtual int area (void) =0; 
        void printarea (void) 
          { cout << this.>area() << endl; } 
      }; 
     
    class CRectangle: public CPolygon { 
      public: 
        int area (void) 
          { return (width * height); } 
      }; 
     
    class CTriangle: public CPolygon { 
      public: 
        int area (void) 
          { return (width * height / 2); } 
      }; 
     
    int main () { 
      CPolygon * ppoly1 = new CRectangle; 
      CPolygon * ppoly2 = new CTriangle; 
      ppoly1->set_values (4,5); 
      ppoly2->set_values (4,5); 
      ppoly1->printarea(); 
      ppoly2->printarea(); 
      delete ppoly1; 
      delete ppoly2; 
      return 0; 
    }
    

     

    输出:20 10

    原文:http://www.cplusplus.com/doc/tutorial/polymorphism/

  • 相关阅读:
    git提交步骤
    封装ajax方法
    review的一个收获popstate,addEventListener:false ,split,jquery cache
    y=y||'world'与y=y?y:'world'
    toString()和toLocaleString()有什么区别
    0,null,undefined,[],{},'',false之间的关系
    小白封装小程序的公共方法时一些笔记
    小程序的一个tab切换
    MVC源码分析
    MVC源码解析
  • 原文地址:https://www.cnblogs.com/dahai/p/2057213.html
Copyright © 2020-2023  润新知