c++学习笔记

来源:互联网 发布:齐鲁石化网络电视台 编辑:程序博客网 时间:2024/05/01 13:13

c++学习笔记
参考:程序员实验室
http://www.prglab.com/cms/pages/c-tutorial/oo-programming/classes.php

类(Classes)

private :class的private成员,只有同一个class的其他成员或该class的“friend” class可以访问这些成员。
protected :class的protected成员,只有同一个class的其他成员,或该class的“friend” class,或该class的子类(derived classes) 可以访问这些成员。
public :class的public成员,任何可以看到这个class的地方都可以访问这些成员。
如果我们在定义一个class成员的时候没有声明其允许范围,这些成员将被默认为 private范围

例如:
定义类:
  class CRectangle {           
       int x, y;       
   public:           
       void set_values (int,int);           
       int area (void);   
  } rect;
使用类:
    #include <iostream.h>
    class CRectangle {
            int x, y;
        public:
            void set_values (int,int);//定义原型
            int area (void)
            {
             return (x*y);
            }
    };
   
    void CRectangle::set_values (int a, int b) {//class外定义该class的成员
        x = a;
        y = b;
    }
   
    int main () {
        CRectangle rect;
        rect.set_values (3,4);
        cout << "area: " << rect.area();
    }
   
说明:
  上面程序中使用了范围操作符(双冒号::),用来在一个class之外定义该class的成员set_value(),class内部只是定义了
  它的原型prototype。范围操作符 (::) 声明了被定义的成员所属的class名称,并赋予被定义成员适当的范围属性,
  这些范围属性与在class内部定义成员的属性是一样的。
区别:
  在class内部直接定义完整的函数,和只定义函数的原型而把具体实现放在class外部的唯一区别在于:
  在第一种情况中,编译器(compiler) 会自动将函数作为inline考虑,inline定义类的内联函数,取代c语言中表达式形式的
  宏定义;而在第二种情况下,函数只是一般的class成员函数。

 


构造函数和析构函数 (Constructors and destructors)

构造函数 constructor
  它可以通过声明一个与class同名的函数来定义。当且仅当要生成一个class的新的实例 (instance)的时候,也就是当且仅
  当声明一个新的对象,或给该class的一个对象分配内存的时候,这个构造函数将自动被调用。
  一个构造函数永远没有返回值,也不用声明void。
  例子:
   // class example
    #include <iostream.h>
   
    class CRectangle {
        int width, height;
      public:
        CRectangle (int,int);
        int area (void) {return (width*height);}
    };
   
    CRectangle::CRectangle (int a, int b) {
        width = a;
        height = b;
    }
   
    int main () {
        CRectangle rect (3,4);
        CRectangle rectb (5,6);
        cout << "rect area: " << rect.area() << endl;
        cout << "rectb area: " << rectb.area() << endl;
    }

析构函数Destructor
  完成相反的功能。它在objects被从内存中释放的时候被自动调用。释放可能是因为它存在的范围已经结束了(例如,
  如果object被定义为一个函数内的本地(local)对象变量,而该函数结束了);或者是因为它是一个动态分配的对象,
  而被使用操作符delete释放了。析构函数必须与class同名,加水波号tilde (~) 前缀,必须无返回值。
  析构函数特别适用于当一个对象被动态分配内存空间,而在对象被销毁时我们希望释放它所占用的空间的时候。
    例子:
    // example on constructors and destructors
    #include <iostream.h>
   
    class CRectangle {
        int *width, *height;
      public:
        CRectangle (int,int);
        ~CRectangle ();
        int area (void) {return (*width * *height);}
    };
   
    CRectangle::CRectangle (int a, int b) {
        width = new int;
        height = new int;
        *width = a;
        *height = b;
    }
   
    CRectangle::~CRectangle () {
        delete width;
        delete height;
    }
   
    int main () {
        CRectangle rect (3,4), rectb (5,6);
        cout << "rect area: " << rect.area() << endl;
        cout << "rectb area: " << rectb.area() << endl;
        return 0;
    }
 
   
   
构造函数重载(Overloading Constructors)
  像其它函数一样,一个构造函数也可以被多次重载(overload)为同样名字的函数,但有不同的参数类型和个数。记住,编译
  器会调用与在调用时刻要求的参数类型和个数一样的那个函数。在这里则是调用与类对象被声明时一样的那个构造函数。   
  两个默认构造函数:
  class CExample {    
   public:      
    int a,b,c;      
    void multiply (int n, int m) { a=n; b=m; c=a*b; };  
  };
  没有定义构造函数,编译器自动假设它有以下constructor 成员函数:

   1.Empty constructor
  它是一个没有任何参数的构造函数,被定义为nop (没有语句)。它什么都不做。
  
  CExample::CExample () { };
  
  2.Copy constructor
  它是一个只有一个参数的构造函数,该参数是这个class的一个对象,这个函数的功能是将被传入的对象(object)的所有非
  静态(non-static)成员变量的值都复制给自身这个object。

    CExample::CExample (const CExample& rv) {      
     a=rv.a; 
     b=rv.b; 
   c=rv.c;  
    }
   例子:
   // overloading class constructors
    #include <iostream.h>
   
    Class CRectangle {
        int width, height;
      public:
        CRectangle ();
        CRectangle (int,int);
        int area (void) {return (width*height);}
    };
   
    CRectangle::CRectangle () {
        width = 5;
        height = 5;
    }
   
    CRectangle::CRectangle (int a, int b) {
        width = a;
        height = b;
    }
   
    int main () {
        CRectangle rect (3,4);
        CRectangle rectb;
        cout << "rect area: " << rect.area() << endl;
        cout << "rectb area: " << rectb.area() << endl;
    }
  注意:在我们声明一个新的object的时候,如果不想传入参数,则不需要写括号():


类的指针(Pointers to classes)
  CRectangle * prect;
  是一个指向class CRectangle类型的对象的指针,使用->引用对象的成员。
  例子:
  // pointer to classes example
    #include <iostream.h>
   
    class CRectangle {
        int width, height;
      public:
        void set_values (int, int);
        int area (void) {return (width * height);}
    };
   
    void CRectangle::set_values (int a, int b) {
        width = a;
        height = b;
    }
   
    int main () {
        CRectangle a, *b, *c;
        CRectangle * d = new CRectangle[2];
        b= new CRectangle;
        c= &a;
        a.set_values (1,2);
        b->set_values (3,4);
        d->set_values (5,6);
        d[1].set_values (7,8);
        cout << "a area: " << a.area() << endl;
        cout << "*b area: " << b->area() << endl;
        cout << "*c area: " << c->area() << endl;
        cout << "d[0] area: " << d[0].area() << endl;
        cout << "d[1] area: " << d[1].area() << endl;
        return 0;
    }
 
 运行:
  a area: 2
  *b area: 12
  *c area: 2
  d[0] area: 30
  d[1] area: 56
  
操作符重载(Overloading operators)
 
 +    -    *    /    =    <    >    +=   -=   *=   /=  
 <<   >> <<=  >>=  ==   !=   <=   >=   ++   --   %    & 
 ^    !    | ~    &=   ^=   |=   &&   ||   %=   []   ()   new  delete 
 我们要计算二维向量(bidimensional vector) a(3,1) 与b(1,2)的和。两个二维向量相加的操作很简单,就是将两个x 轴的
 值相加获得结果的x 轴值,将两个 y 轴值相加获得结果的 y值。在这个例子里,结果是 (3+1,1+2) = (4,3)。
 例子:
     // vectors: overloading operators example
    #include <iostream.h>
   
    class CVector {
      public:
        int x,y;
        CVector () {};
        CVector (int,int);//CVector是函数名称
        CVector operator + (CVector);// 函数 operator+ 返回CVector 类型的值
    };
   
    CVector::CVector (int a, int b) {
        x = a;
        y = b;
    }
   
    CVector CVector::operator+ (CVector param) {
        CVector temp;
        temp.x = x + param.x;
        temp.y = y + param.y;
        return (temp);
    }
   
    int main () {
        CVector a (3,1);
        CVector b (1,2);
        CVector c;
        c = a + b;
        cout << c.x << "," << c.y;
        return 0;
    }
Class CVector的函数 operator+ 是对数学操作符+进行重载的函数。这个函数可以用以下两种方法进行调用:
 c = a + b;
 c = a.operator+ (b);
 
关键字 this
 关键字this 通常被用在一个class内部,指正在被执行的该class的对象(object)在内存中的地址。它是一个指针,其值永远
 是自身object的地址。
 1.它可以被用来检查传入一个对象的成员函数的参数是否是该对象本身。
 2.它还经常被用在成员函数operator= 中,用来返回对象的指针(避免使用临时对象)。


静态成员(Static members)
 一个class 可以包含静态成员(static members),可以是数据,也可以是函数。

 一个class的静态数据成员也被称作类变量"class variables",因为它们的内容不依赖于某个对象,对同一个class的所有
 object具有相同的值。
 它可以被用作计算一个class声明的objects的个数,例子:
     // static members in classes
    #include <iostream.h>
   
    class CDummy {
      public:
        static int n;//静态数据成员n
        CDummy () { n++; };
        ~CDummy () { n--; };
    };
   
    int CDummy::n=0;
   
    int main () {
        CDummy a;
        CDummy b[5];
        CDummy * c = new CDummy;
        cout << a.n << endl;
        delete c;
        cout << CDummy::n << endl;
        return 0;
    }
 
 实际上,静态成员与全域变量(global variable)具有相同的属性,但它享有类(class)的范围。因此,根据ANSI-C++ 标准,
 为了避免它们被多次重复声明,在class的声明中只能够包括static member的原型(声明),而不能够包括其定义(初始化操作)。
 为了初始化一个静态数据成员,我们必须在class之外(在全域范围内),包括一个正式的定义,就像上面例子中做法一样。

 因为它对同一个class的所有object是同一个值,所以它可以被作为该class的任何object的成员所引用,或者直接被作为class
 的成员引用(当然这只适用于static 成员):
 
 cout << a.n;
 cout << CDummy::n;
 以上两个调用都指同一个变量:class CDummy里的static 变量 n 。
 
 再提醒一次,它其实是一个全域变量。唯一的不同是它的名字跟在class的后面。
 
 就像我们会在class中包含static数据一样,我们也可以使它包含static 函数。它们表示相同的含义:static函数是全域函
 数(global functions),但是像一个指定class的对象成员一样被调用。它们只能够引用static 数据,永远不能引用class
 的非静态(nonstatic)成员。它们也不能够使用关键字this,因为this实际引用了一个对象指针,但这些 static函数却不是
 任何object的成员,而是class的直接成员。


类之间的关系

 友元函数(friend functions)
 在前面的章节中我们已经看到了对class的不同成员存在3个层次的内部保护:public, protected 和 private。在成员为
 protected 和 private的情况下,它们不能够被从所在的class以外的部分引用。然而,这个规则可以通过在一个class中使用
 关键字friend来绕过,这样我们可以允许一个外部函数获得访问class的protected 和 private 成员的能力。

 为了实现允许一个外部函数访问class的private 和 protected 成员,我们必须在class内部用关键字friend来声明该外部函数
 的原型,以指定允许该函数共享class的成员。在下面的例子中我们声明了一个 friend 函数 duplicate:
     // friend functions
    #include <iostream.h>
   
    class CRectangle {
        int width, height;
      public:
        void set_values (int, int);
        int area (void) {return (width * height);}
        friend CRectangle duplicate (CRectangle);
    };
   
    void CRectangle::set_values (int a, int b) {
        width = a;
        height = b;
    }
   
    CRectangle duplicate (CRectangle rectparam) {
        CRectangle rectres;
        rectres.width = rectparam.width*2;
        rectres.height = rectparam.height*2;
        return (rectres);
    }
   
    int main () {
        CRectangle rect, rectb;
        rect.set_values (2,3);
        rectb = duplicate (rect);
        cout << rectb.area();
    }
注意:
在 duplicate()的声明中,及其在后面main()里被调用的时候,我们并没有把duplicate 当作class CRectangle的成员,它不是。


友元类()
 就像我们可以定义一个friend 函数,我们也可以定义一个class是另一个的friend,以便允许第二个class访问第一个class
 的 protected 和 private 成员。
 例子:
     // friend class
    #include <iostream.h>
   
    class CSquare;

    class CRectangle {
        int width, height;
      public:
        int area (void) {return (width * height);}
        void convert (CSquare a);
    };
   
    Class CSquare {
      private:
        int side;
      public:
        void set_side (int a){side=a;}
        friend class CRectangle;
    };
   
    void CRectangle::convert (CSquare a) {
        width = a.side;
        height = a.side;
    }
   
    int main () {
        CSquare sqr;
        CRectangle rect;
        sqr.set_side(4);
        rect.convert(sqr);
        cout << rect.area();
        return 0;
    }
 在这个例子中,我们声明了CRectangle 是CSquare 的friend,因此CRectangle可以访问CSquare 的protected 和 private 成员,
 更具体地说,可以访问CSquare::side,它定义了正方形的边长。
 
 在上面程序的第一个语句里你可能也看到了一些新的东西,就是class CSquare空原型。这是必需的,因为在CRectangle 的声
 明中我们引用了CSquare (作为convert()的参数)。CSquare 的定义在CRectangle的后面,因此如果我们没有在这个class之前
 包含一个CSquare 的声明,它在CRectangle中就是不可见的。

 这里要考虑到,如果没有特别指明,友元关系(friendships)并不是相互的。在我们的CSquare 例子中,CRectangle 是一个
 friend类,但因为CRectangle 并没有对CSquare作相应的声明,因此CRectangle 可以访问CSquare 的 protected 和private
  成员,但反过来并不行,除非我们将 CSquare 也定义为CRectangle的 friend。


类之间的继承(Inheritance between classes)

 由其它类引申而来的子类继承基类的所有可视成员,意思是说,如果一个基类包含成员A ,而我们将它引申为另一个包含成员B
 的类,则这个子类将同时包含 A 和 B。要定义一个类的子类,我们必须在子类的声明中使用冒号(colon)操作符: ,
 如下所示:
 
 class derived_class_name: public base_class_name;
 
 这里derived_class_name 为子类(derived class)名称,base_class_name 为基类(base class)名称。public 也可以根据需要
 换为protected 或 private,描述了被继承的成员的访问权限。
 
 标识符protected 与 private类似,它们的唯一区别在继承时才表现出来。当定义一个子类的时候,基类的protected 成员可
 以被子类的其它成员所使用,然而private 成员就不可以。
 
 下表按照谁能访问总结了不同访问权限类型:
 可以访问     public protected private
 本class的成员  yes   yes    yes
 子类的成员    yes   yes     no
 非成员      yes   no      no

这里"非成员"指从class以外的任何地方引用,例如从main()中,从其它的class中或从全域(global)或本地(local)的任何函数中。
 
 这是因为我们在继承的时候使用的是public,记得我们用的是:
 class CRectangle: public CPolygon;
 这里关键字 public 表示新的类(CRectangle)从基类(CPolygon)所继承的成员必须获得最低程度保护。这种被继承成员的访问
 限制的最低程度可以通过使用 protected 或 private而不是public来改变。例如,daughter 是mother 的一个子类,我们可以
 这样定义:

 class daughter: protected mother;
 这将使得protected 成为daughter 从mother处继承的成员的最低访问限制。也就是说,原来mother 中的所有public 成员到
 daughter 中将会成为protected 成员,这是它们能够被继承的最低访问限制。当然这并不是限制daughter 不能有它自己的
 public 成员。最低访问权限限制只是建立在从mother中 继承的成员上的。

 最常用的继承限制除了public 外就是private ,它被用来将基类完全封装起来,因为在这种情况下,除了子类自身外,其它任
 何程序都不能访问那些从基类继承而来的成员。不过大多数情况下继承都是使用public的。

 如果没有明确写出访问限制,所有由关键字class 生成的类被默认为private ,而所有由关键字struct 生成的类被默认为public

什么是从基类中继承的? (What is inherited from the base class?)

理论上说,子类(drived class)继承了基类(base class)的所有成员,除了:
构造函数Constructor 和析构函数destructor
operator=() 成员
friends

虽然基类的构造函数和析构函数没有被继承,但是当一个子类的object被生成或销毁的时候,其基类的默认构造函数 (即,没有
任何参数的构造函数)和析构函数总是被自动调用的。

如果基类没有默认构造函数,或你希望当子类生成新的object时,基类的某个重载的构造函数被调用,你需要在子类的每一个构造
函数的定义中指定它:

derived_class_name (parameters) : base_class_name (parameters) {}
例如 (注意程序中黑体的部分):
    // constructors and derivated classes
    #include <iostream.h>
   
    class mother {
      public:
        mother ()
          { cout << "mother: no parameters\n"; }
        mother (int a)
          { cout << "mother: int parameter\n"; }
    };
   
    class daughter : public mother {
      public:
        daughter (int a) // 没有特别制定:调用默认constructor
          { cout << "daughter: int parameter\n\n"; }
    };
   
    class son : public mother {
      public:
        son (int a) : mother (a) // 指定了constructor: 调用被指定的构造函数
          { cout << "son: int parameter\n\n"; }
    };
   
    int main () {
        daughter cynthia (1);
        son daniel(1);
        return 0;
    }
运行结果:
mother: no parameters
daughter: int parameter

mother: int parameter
son: int parameter

多重继承(Multiple inheritance)
 在C++ 中,一个class可以从多个class中继承属性或函数,只需要在子类的声明中用逗号将不同基类分开就可以了。例如,
 如果我们有一个特殊的class COutput 可以实现向屏幕打印的功能,我们同时希望我们的类CRectangle 和 CTriangle 在
 CPolygon 之外还继承一些其它的成员,我们可以这样写:

 class CRectangle: public CPolygon, public COutput {
 class CTriangle: public CPolygon, public COutput {
   例子:
    // multiple inheritance
    #include <iostream.h>
   
    class CPolygon {
      protected:
        int width, height;
      public:
        void set_values (int a, int b)
          { width=a; height=b;}
    };
   
    class COutput {
      public:
        void output (int i);
    };
   
    void COutput::output (int i) {
        cout << i << endl;
    }
   
    class CRectangle: public CPolygon, public COutput {
      public:
        int area (void)
          { return (width * height); }
    };
   
    class CTriangle: public CPolygon, public COutput {
      public:
        int area (void)
          { return (width * height / 2); }
    };
   
    int main () {
        CRectangle rect;
        CTriangle trgl;
        rect.set_values (4,5);
        trgl.set_values (4,5);
        rect.output (rect.area());
        trgl.output (trgl.area());
        return 0;
    }


4.4 多态 (Polymorphism)

基类的指针(Pointers to base class)

 继承的好处之一是一个指向子类(derived class)的指针与一个指向基类(base class)的指针是type-compatible的。 本节就是重
 点介绍如何利用C++的这一重要特性。例如,我们将结合C++的这个功能,重写前面小节中关于长方形rectangle 和三角形
 triangle 的程序:
 #include <iostream.h>
 class CPolygon {
 protected:
     int width, height;
 public:
     void set_values (int a, int b) {
         width=a; height=b;
     }
 };
 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 << rect.area() << endl;
     cout << trgl.area() << endl;
     return 0;
 }
 在主函数 main 中定义了两个指向class CPolygon的对象的指针,即 *ppoly1 和 *ppoly2。 它们被赋值为rect 和 trgl的地址,
 因为rect 和 trgl是CPolygon 的子类的对象,因此这种赋值是有效的。

 使用*ppoly1 和 *ppoly2 取代rect 和trgl 的唯一限制是*ppoly1 和 *ppoly2 是CPolygon* 类型的,因此我们只能够引用
 CRectangle 和 CTriangle 从基类CPolygon中继承的成员。正是由于这个原因,我们不能够使用*ppoly1 和 *ppoly2 来调用
 成员函数 area(),而只能使用rect 和 trgl来调用这个函数。

 要想使CPolygon 的指针承认area()为合法成员函数,必须在基类中声明它,而不能只在子类进行声明(见下一小节)。

虚拟成员(Virtual members)
 如果想在基类中定义一个成员留待子类中进行细化,我们必须在它前面加关键字virtual ,以便可以使用指针对指向相应的对象进行操作。

 请看一下例子:
 
 // virtual members
 #include <iostream.h>
 class CPolygon {
     protected:
         int width, height;
     public:
         void set_values (int a, int b)  {
             width=a;
             height=b;
         }
         virtual int area (void) { return (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 poly;
     CPolygon * ppoly1 = &rect;
     CPolygon * ppoly2 = &trgl;
     CPolygon * ppoly3 = &poly;
     ppoly1->set_values (4,5);
     ppoly2->set_values (4,5);
     ppoly3->set_values (4,5);
     cout << ppoly1->area() << endl;
     cout << ppoly2->area() << endl;
     cout << ppoly3->area() << endl;
     return 0;
 }
 现在这三个类(CPolygon, CRectangle 和 CTriangle) 都有同样的成员:width, height, set_values() 和 area()。

 area() 被定义为virtual 是因为它后来在子类中被细化了。你可以做一个试验,如果在代码种去掉这个关键字(virtual),然后
 再执行这个程序,三个多边形的面积计算结果都将是 0 而不是20,10,0。这是因为没有了关键字virtual ,程序执行不再根据实
 际对象的不用而调用相应area() 函数(即分别为CRectangle::area(), CTriangle::area() 和 CPolygon::area()),取而代之,
 程序将全部调用CPolygon::area(),因为这些调用是通过CPolygon类型的指针进行的。

 因此,关键字virtual 的作用就是在当使用基类的指针的时候,使子类中与基类同名的成员在适当的时候被调用,如前面例子中
 所示。

 注意,虽然本身被定义为虚拟类型,我们还是可以声明一个CPolygon 类型的对象并调用它的area() 函数,它将返回0 ,如前面
 例子结果所示。


抽象基类(Abstract base classes)

 基本的抽象类与我们前面例子中的类CPolygon 非常相似,唯一的区别是在我们前面的例子中,我们已经为类CPolygon的对象
 (例如对象poly)定义了一个有效地area()函数,而在一个抽象类(abstract base class)中,我们可以对它不定义,而简单
 得在函数声明后面写 =0 (等于0)。
 类CPolygon 可以写成这样:
 class CPolygon {
     protected:
         int width, height;
     public:
         void set_values (int a, int b) {
             width=a;
             height=b;
         }
         virtual int area (void) =0;
 };
 注意我们是如何在virtual int area (void)加 =0 来代替函数的具体实现的。这种函数被称为纯虚拟函数(pure virtual
  function),而所有包含纯虚拟函数的类被称为抽象基类(abstract base classes)。
 抽象基类的最大不同是它不能够有实例(对象),但我们可以定义指向它的指针。
 因此,像这样的声明:
 CPolygon poly;
 
 对于前面定义的抽象基类是不合法的。
 
 然而,指针:
 
 CPolygon * ppoly1;
 CPolygon * ppoly2

 是完全合法的。这是因为该类包含的纯虚拟函数(pure virtual function) 是没有被实现的,而又不可能生成一个不包含它的所
 有成员定义的对象。然而,因为这个函数在其子类中被完整的定义了,所以生成一个指向其子类的对象的指针是完全合法的。
 下面是完整的例子:

// virtual members
#include <iostream.h>
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;
}
再看一遍这段程序,你会发现我们可以用同一种类型的指针(CPolygon*)指向不同类的对象,这一点非常有用。 想象一下,现在
我们可以写一个CPolygon 的成员函数,使得它可以将函数area()的结果打印到屏幕上,而不必考虑具体是为哪一个子类。
#include <iostream.h>
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;
}

记住,this 代表代码正在被执行的这一个对象的指针。

抽象类和虚拟成员赋予了C++ 多态(polymorphic)的特征,使得面向对象的编程object-oriented programming成为一个有用的工具。
这里只是展示了这些功能最简单的用途。想象一下如果在对象数组或动态分配的对象上使用这些功能,将会节省多少麻烦。

 

 

 


 

0 0