多态性
进入本节之前,建议你有一个正确的理解指针和类继承。 如果下面的语句似乎怪你,你应该检讨指定的章节:声明: | 解释: |
---|---|
的INT A :: B(C){} | 班 |
A-> B | 数据结构 |
A级:公众B {}; | 友谊和继承 |
基类的指针
派生类的主要特点之一是其基类的指针到派生类的指针类型兼容。 多态性是艺术趁着这个简单但功能强大和灵活的功能,带来了面向对象的方法,以充分发挥其潜力。我们要开始的矩形和三角形上一节考虑这指针兼容性属性重写我们的程序:
| | 20 10 |
在main函数中,我们创建了两个指向,以对象类CPolygon(ppoly1 ppoly2)的。 然后我们分配引用rect和TRGL的这些指针,因为两者都是CPolygon的派生类的对象,都是有效的分配操作。
唯一的限制在使用* ppoly1和* ppoly2代替rect和TRGL的是,这两个* ppoly1和* ppoly2是CPolygon的*类型,因此我们只能使用这些指针来引用, 类CRectangle和 CTriangle的继承CPolygon的成员。 出于这个原因,当我们调用的区域()的节目结束时,我们不得不直接使用的对象rect和TRGL的 ,而不是指针* ppoly1和* ppoly2成员。
类CPolygon的指针以使用面积(),则该成员应也已宣布在类CPolygon,不仅在它的派生类,但问题是, 类CRectangle和CTriangle的实施地区的不同版本,因此我们不能执行,在基类中。 这是虚拟成员时变得得心应手:
虚拟成员
被称为虚拟成员的类的一个成员在派生类可以重新定义。 为了申报一类作为虚拟的一员,我们必须先声明virtual关键字: | | 20 10 0 |
现在三类( 圈交 , 类CRectangle和 CTriangle的),有相同的成员: 宽度 , 高度中, 函数set_values()和面积()。
区域()成员函数被声明为虚基类中的,因为它是后来每个派生类中重新定义。 您可以验证,如果你想,如果你删除这个虚拟的关键字从申报区域()在CPolygon的范围内 ,然后运行程序,结果将是0三个多边形,而不是20,10和0。 ,而不是调用相应区域()函数的每个对象(CRectangle的区域(),CTriangle ::面积()和圈交::面积 ,这是因为(),分别),将被称为圈交::面积()所有情况下,因为这些调用是通过指针的类型是CPolygon的*。
因此, 虚拟关键字的作用是允许一个派生类的成员具有相同的名称作为一个在基类中被适当地称为从一个指针,和更精确地,当不同的指针是一个指针到基类但指向派生的类的一个对象,如在上面的例子。
声明或继承了虚函数的类称为多态类 。
请注意,尽管它的虚拟性,我们也能够CPolygon类型来声明对象,并呼吁自己的领域()函数,它总是返回0。
抽象基类
抽象基类的东西非常类似我们前面的例子我们CPolygon的类。 唯一的区别是,在我们前面的例子中,我们定义的有效面积()函数的的类CPolygon(如对象聚 )为对象,用最少的功能,而在一个抽象基类,我们可以离开那个区域()成员在所有没有实现的功能。 这是通过附加到函数声明= 0(等于零)。一个抽象基CPolygon的类可能看起来像这样:
| |
注意我们如何附加= 0到虚拟的int区(),而不是指定一个实现的功能。 这种类型的函数称为纯虚函数 ,所有至少包含一个纯虚函数的类是抽象基类 。
一个抽象基类和普通的多态类之间的主要区别是,因为至少有一个抽象基类,其成员缺乏实现,我们不能创建它的实例(对象)。
但也不是完全无用的一类,不能实例化对象。 我们可以创建指向它的指针,并充分利用其所有的多态能力。 因此,声明如下:
| |
不会有效的抽象基类,我们刚刚宣布,因为试图实例化一个对象。 然而,下面的指针:
| |
将是完全有效的。
之所以如此,是CPolygon的 ,只要有一个纯虚函数,因此它是一个抽象基类。 然而,可以使用这个抽象基类的指针指向派生类的对象。
在这里,你有完整的例子:
| | 20 10 |
如果您查看程序,你会发现,我们称之为不同的,但相关的类的对象使用一个独特的类型的指针( 圈交*)。 这可以是相当有用的。 例如,现在我们可以创建一个函数成员的抽象基类CPolygon即能在屏幕上打印的区域()的结果CPolygon的本身功能,即使没有实现这个功能:
| | 20 10 |
虚拟成员和抽象类出让C + +的多态性面向对象编程的特点,使大项目中的一个有用的工具。 当然,我们已经看到了非常简单的使用这些功能,但这些功能都可以应用到对象的数组或动态分配的对象。
让我们再次结束,同样的例子,但这次与动态分配的对象:
| | 20 10 |
请注意,的ppoly指针:
| |