【译】多态(二)
抽象基类
抽象基类很像我们之前例子的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 = ▭
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 = ▭
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
浙公网安备 33010602011771号