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 = ▭ 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 }
在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 = ▭ 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 }
输出结果:
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 };
注意此时 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 = ▭ 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 }
这个例子中都是由基类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 = ▭ 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 }
虚成员和抽象类赋予了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 }
此处基类指针声明时直接用的派生类。
上一篇: Java的递归、IO流
下一篇: 回话处理程序(17)