C++抽象基类和纯虚成员函数
公共接口是指一系列成员函数的集合,支持该接口的类必须以合适的方式重新定义这些成员函数,否则就无法创建对象。C++ 中可以通过抽象基类来实现公共接口,为了介绍抽象基类,我们需要先来了解一下纯虚成员函数。
纯虚成员函数的声明语法如下:
包含纯虚成员函数的类即为抽象基类,之所以说它抽象,那是因为它无法实例化,也即无法用于创建对象。
【例 1】
纯虚成员函数可以被派生类继承,如果派生类不重新定义抽象基类中的所有(有多个则要重新定义多个)纯虚成员函数,则派生类同样会成为抽象基类,也不能用于创建对象。
【例 2】
再来看一下主函数中的情况:
一个纯虚成员函数就可以使类成为抽象基类,但是抽象基类中除了包含纯虚成员函数外,同样可以包含其它成员函数或成员变量。如例 2 中所示的 base 类,类中除了包含纯虚成员函数之外,还包含了一个 private 成员变量 x 和两个构造函数及一个普通成员函数 getx()。
只有类中的虚函数才能被声明为纯虚成员函数,普通成员函数和顶层函数均不能声明为纯虚成员函数。如例 3 中企图将顶层函数和普通的成员函数声明为纯虚成员函数,这都是不允许的。
【例 3】
声明:《C++系列教程》为本站“54笨鸟”官方原创,由国家机构和地方版权局所签发的权威证书所保护。
纯虚成员函数的声明语法如下:
virtual 函数返回类型 函数名 (函数参数) = 0;
纯虚成员函数没有函数体,只有函数声明,在纯虚函数声明结尾加上“=0”表明此函数为纯虚成员函数。包含纯虚成员函数的类即为抽象基类,之所以说它抽象,那是因为它无法实例化,也即无法用于创建对象。
【例 1】
#include<iostream> using namespace std; class base { public : virtual void display() = 0; //...... }; int main() { base b; //compile error return 0; }如本例所示,本例中只定义了一个 base 类,该类中声明了一个纯虚成员函数,包含纯虚成员函数的类即为抽象基类,因此 base 类为抽象基类。抽象基类是无法用于创建对象的,而主函数中我们尝试创建 base 类的对象,这是不允许的,编译提示语法错误。
纯虚成员函数可以被派生类继承,如果派生类不重新定义抽象基类中的所有(有多个则要重新定义多个)纯虚成员函数,则派生类同样会成为抽象基类,也不能用于创建对象。
【例 2】
#include<iostream> using namespace std; class base { public : base(){x = 0;} base(int a){x = a;} virtual void display() = 0; int getx(){return x;} private: int x; }; class derived1 : public base { public: derived1(int a){ y = a;} private: int y; }; class derived2 : public base { public: derived2(int a, int b):base(a){ z = b;} void display() { cout<<getx()<<" "<<z<<endl; } private: int z; } int main() { base b; //compile error derived1 d1(5); //compile error derived2 d2(5,6); d2.display(); return 0; }在本例中定义了三个类:
- base 类中有一个整型成员变量 x、两个构造函数、一个 getx() 普通成员函数和一个 display() 纯虚成员函数。
- derived1 类继承自 base 类,该类中新增一个整型的成员变量 y,并且定义了一个构造函数。
- derived2 类也继承自 base 类,该类同样新增了一个整型的成员变量 z,并且定义了一个带参的构造函数,还显式调用了基类中的构造函数。除此之外,derived2 类还重新定义了基类中的纯虚成员函数 display(),派生类中的 display() 函数与基类中的纯虚成员函数构成函数覆盖。
再来看一下主函数中的情况:
- 首先尝试创建 base 类的对象,因为 base 类包含一个纯虚成员函数,所以是抽象基类,不能创建对象;
- 又尝试创建 derived1 的对象,derived1 类继承了基类 base 中的纯虚成员函数,并且没有重新定义该函数,因此 derived1 类虽然是 base 类的派生类,但它仍然是抽象基类,因此同样不能创建对象。
- 最后尝试创建 derived2 类的对象,该类同样是 base 类的派生类,同样从 base 类中继承了纯虚成员函数 display()。但是,该类中重新定义了 display() 函数,覆盖了基类的 display() 纯虚成员函数,因此该类不是抽象基类,可以创建对象。创建 derived2 类的对象时调用了类中的带参构造函数,之后通过对象调用 display() 函数,打印出成员变量 x 和 y 的值。
一个纯虚成员函数就可以使类成为抽象基类,但是抽象基类中除了包含纯虚成员函数外,同样可以包含其它成员函数或成员变量。如例 2 中所示的 base 类,类中除了包含纯虚成员函数之外,还包含了一个 private 成员变量 x 和两个构造函数及一个普通成员函数 getx()。
只有类中的虚函数才能被声明为纯虚成员函数,普通成员函数和顶层函数均不能声明为纯虚成员函数。如例 3 中企图将顶层函数和普通的成员函数声明为纯虚成员函数,这都是不允许的。
【例 3】
void fun() = 0; //compile error class base { public : void display() = 0; //compile error //...... };抽象基类可以用于实现公共接口,在抽象基类中声明的纯虚成员函数,派生类如果想要能够创建对象,则必须全部重新定义这些纯虚成员函数。
声明:《C++系列教程》为本站“54笨鸟”官方原创,由国家机构和地方版权局所签发的权威证书所保护。