C++多态

C++多态

Polymorphism

本文为C++官网对多态阐述:http://www.cplusplus.com/doc/tutorial/polymorphism/

在了解多态前需具备如下知识:类、结构体、友元和继承。

指向基类的指针

先来看一个基础例子

 1 // pointers to base class
 2 #include <iostream>
 3 using namespace std;
 4 
 5 class Polygon {
 6   protected:
 7     int width, height;
 8   public:
 9     void set_values (int a, int b)
10       { width=a; height=b; }
11 };
12 
13 class Rectangle: public Polygon {
14   public:
15     int area()
16       { return width*height; }
17 };
18 
19 class Triangle: public Polygon {
20   public:
21     int area()
22       { return width*height/2; }
23 };
24 
25 int main () {
26   Rectangle rect;
27   Triangle trgl;
28   Polygon * ppoly1 = &rect;
29   Polygon * ppoly2 = &trgl;
30   ppoly1->set_values (4,5);
31   ppoly2->set_values (4,5);
32   cout << rect.area() << '\n';
33   cout << trgl.area() << '\n';
34   return 0;
35 }
pointers to base class

 在Rectangle和Triangle类中都含有函数area()。main函数中是分别用类对象直接调用。由于Polygon类中没有area成员函数,故ppoly1和ppoly2指针无法调用该函数。如果在基类中也能调用area()那么就不用上面代码中分别调用那么麻烦了,不过问题是area()方法不统一,没法在基类中实现。

虚成员

虚成员是一种能在派生类中重定义的成员函数,通过关键字 virtual 声明。

 1 // virtual members
 2 #include <iostream>
 3 using namespace std;
 4 
 5 class Polygon {
 6   protected:
 7     int width, height;
 8   public:
 9     void set_values (int a, int b)
10       { width=a; height=b; }
11     virtual int area ()
12       { return 0; }
13 };
14 
15 class Rectangle: public Polygon {
16   public:
17     int area ()
18       { return width * height; }
19 };
20 
21 class Triangle: public Polygon {
22   public:
23     int area ()
24       { return (width * height / 2); }
25 };
26 
27 int main () {
28   Rectangle rect;
29   Triangle trgl;
30   Polygon poly;
31   Polygon * ppoly1 = &rect;
32   Polygon * ppoly2 = &trgl;
33   Polygon * ppoly3 = &poly;
34   ppoly1->set_values (4,5);
35   ppoly2->set_values (4,5);
36   ppoly3->set_values (4,5);
37   cout << ppoly1->area() << '\n';
38   cout << ppoly2->area() << '\n';
39   cout << ppoly3->area() << '\n';
40   return 0;
41 }
virtual members

输出结果:

20

10

0     

在Polygon类中函数 area 被声明成 virtual 因为他将被每个派生类重定义。虽然没有关键字 virtual 函数area也能派生类重定义,但是非虚成员不能被派生类通过基类引用访问。如果此处area前的virtual关键字被去掉,上面三个cout结果都会是0,因为调用的时候会被基类的函数替代。

一个声明或继承了虚函数的类被叫做多态类。

 抽象基类

抽象基类是只能被当作基类,从而被允许拥有未定义的虚成员函数(纯虚函数)。

1 // abstract class CPolygon
2 class Polygon {
3   protected:
4     int width, height;
5   public:
6     void set_values (int a, int b)
7       { width=a; height=b; }
8     virtual int area () =0;
9 };
abstract class

注意此时 area函数未定义;他的定义被=0取代,这使它变成了一个纯虚函数。至少拥有一个纯虚函数的类叫做抽象基类。抽象类不能被实例化,但能使用其指针。

 1 // abstract base class
 2 #include <iostream>
 3 using namespace std;
 4 
 5 class Polygon {
 6   protected:
 7     int width, height;
 8   public:
 9     void set_values (int a, int b)
10       { width=a; height=b; }
11     virtual int area (void) =0;
12 };
13 
14 class Rectangle: public Polygon {
15   public:
16     int area (void)
17       { return (width * height); }
18 };
19 
20 class Triangle: public Polygon {
21   public:
22     int area (void)
23       { return (width * height / 2); }
24 };
25 
26 int main () {
27   Rectangle rect;
28   Triangle trgl;
29   Polygon * ppoly1 = &rect;
30   Polygon * ppoly2 = &trgl;
31   ppoly1->set_values (4,5);
32   ppoly2->set_values (4,5);
33   cout << ppoly1->area() << '\n';
34   cout << ppoly2->area() << '\n';
35   return 0;
36 }
abstract base class

 这个例子中都是由基类Polygon指针调用成员函数。还能在基类中使用this指针调用派生类继承的纯虚函数。

 1 // pure virtual members can be called
 2 // from the abstract base class
 3 #include <iostream>
 4 using namespace std;
 5 
 6 class Polygon {
 7   protected:
 8     int width, height;
 9   public:
10     void set_values (int a, int b)
11       { width=a; height=b; }
12     virtual int area() =0;
13     void printarea()
14       { cout << this->area() << '\n'; }
15 };
16 
17 class Rectangle: public Polygon {
18   public:
19     int area (void)
20       { return (width * height); }
21 };
22 
23 class Triangle: public Polygon {
24   public:
25     int area (void)
26       { return (width * height / 2); }
27 };
28 
29 int main () {
30   Rectangle rect;
31   Triangle trgl;
32   Polygon * ppoly1 = &rect;
33   Polygon * ppoly2 = &trgl;
34   ppoly1->set_values (4,5);
35   ppoly2->set_values (4,5);
36   ppoly1->printarea();
37   ppoly2->printarea();
38   return 0;
39 }
pure virtual members can be called from the abstract base class

虚成员和抽象类赋予了C++多态特性,对面向对象项目用于极大。

以下的例子结合了动态内存、类构造初始化、多态:

 1 // dynamic allocation and polymorphism
 2 #include <iostream>
 3 using namespace std;
 4 
 5 class Polygon {
 6   protected:
 7     int width, height;
 8   public:
 9     Polygon (int a, int b) : width(a), height(b) {}
10     virtual int area (void) =0;
11     void printarea()
12       { cout << this->area() << '\n'; }
13 };
14 
15 class Rectangle: public Polygon {
16   public:
17     Rectangle(int a,int b) : Polygon(a,b) {}
18     int area()
19       { return width*height; }
20 };
21 
22 class Triangle: public Polygon {
23   public:
24     Triangle(int a,int b) : Polygon(a,b) {}
25     int area()
26       { return width*height/2; }
27 };
28 
29 int main () {
30   Polygon * ppoly1 = new Rectangle (4,5);
31   Polygon * ppoly2 = new Triangle (4,5);
32   ppoly1->printarea();
33   ppoly2->printarea();
34   delete ppoly1;
35   delete ppoly2;
36   return 0;
37 }
dynamic allocation and polymorphism

此处基类指针声明时直接用的派生类。

猜你喜欢

转载自www.cnblogs.com/baichenshan/p/8901819.html