C++中抽象基类和纯虚函数
不能实例化的基类被称为抽象基类, 这样的基类只有一个用途, 那就是从它派生出其他类。 在 C++
中,要创建抽象基类,可声明纯虚函数。
以下述方式声明的虚函数被称为纯虚函数:
class AbstractBase
{
public:
virtual void DoSomething() = 0; // pure virtual method
};
该声明告诉编译器, AbstractBase 的派生类必须实现方法 DoSomething( ):
class Derived: public AbstractBase
{
public:
void DoSomething() // pure virtual fn. must be implemented
{
cout << “Implemented virtual function” << endl;
}
};
AbstractBase 类要求 Derived 类必须提供虚方法 DoSomething( )的实现。这让基类可指定派生类中
方法的名称和特征标,即指定派生类的接口。再次以 Tuna 类为例,假定它继承了 Fish 类,但没有覆
盖 Fish::Swim( ),因此不能游得很快。这种实现存在缺陷。通过将 Swim 声明为纯虚函数,让 Fish 变
成抽象基类,可确保从 Fish 派生而来的 Tuna 类实现 Tuna::Swim( ),从而像金枪鱼那样游动,如程序
清单 11.6 所示。
0: #include <iostream>
1: using namespace std;
2:
3: class Fish
4: {
5: public:
6: // define a pure virtual function Swim
7: virtual void Swim() = 0;
8: };
9:
10: class Tuna:public Fish
11: {
12: public:
13: void Swim()
14: {
15: cout << "Tuna swims fast in the sea! " << endl;
16: }
17: };
18:
19: class Carp:public Fish
20: {
21: void Swim()
22: {
23: cout << "Carp swims slow in the lake!" << endl;
24: }
25: };
26:
27: void MakeFishSwim(Fish& inputFish)
28: {
29: inputFish.Swim();
30: }
31:
32: int main()
33: {
34: // Fish myFish; // Fails, cannot instantiate an ABC
35: Carp myLunch;
36: Tuna myDinner;
37:
38: MakeFishSwim(myLunch);
39: MakeFishSwim(myDinner);
40:
41: return 0;
42: }
输出:
Carp swims slow in the lake!
Tuna swims fast in the sea!
分析:
main( )的第 1 行(第 34 行)被注释掉了, 它意义重大。它表明, 编译器不允许您创建抽象基类( ABC)
Fish 的实例。编译器要求您创建具体类(如 Tuna)的对象,这与现实世界一致。第 7 行声明了纯虚函
数 Fish::Swim( ),这迫使 Tuna 和 Carp 必须分别实现 Tuna::Swim( )和 Carp::Swim( )。第 27~30 行实现
了 MakeFishSwim(Fish&),这表明虽然不能实例化抽象基类,但可将指针或引用的类型指定为抽象基
类。抽象基类提供了一种非常好的机制,让您能够声明所有派生类都必须实现的函数。如果 Trout 类从
Fish 类派生而来,但没有实现 Trout::Swim( ),将无法通过编译。