虚函数是指针还是c语言(C语言中的虚函数)
上一节较为详细的讨论了C 语言中基类被派生类继承过程中的内存模型,尤其较为详细的分析了虚函数及其虚表、虚表指针在内存中是如何分布,如何存储的,这对于理解C 语言中的“动态绑定”是极有帮助的。
对于理解C 语言中的“动态绑定”是极有帮助的
正如之前两篇文章所讨论的,C 语言中虚函数的“动态绑定”能为多态的实现带来极大的便利——“动态绑定”机制是在程序运行时根据指针所指向对象的类型(而不是指针本身类型)决定被调用的成员函数,因此在C 语言程序开发中,使用基类指针就可以调用其所有派生类的成员函数。可见,C 语言中的虚函数其实就是为了提升程序员开发的便利设计的。事实上,为了充分利用这种设计带来的便利性,C 语言中还有着“纯虚函数”的概念。
纯虚函数与抽象类所谓“纯虚函数”,其实就是没有具体实现的虚函数,通常定义在基类中提供类似于“接口”的功能。因为没有具体实现,也即该函数没有具体功能,拥有纯虚函数的基类通常被称作“抽象类”,所以抽象类无法实例化对象,一般只能作为基类被其他派生类继承使用。继承了抽象基类的派生类必须重写所有的纯虚函数,也即为类提供具体的功能,才能实例化对象使用。
在C 语言中,只要某个类有纯虚函数,或者继承了抽象类而没有重写所有纯虚函数,那么该类就是“抽象类”,无法实例化对象。
在C 语言中,在类中定义纯虚函数是非常简单的,只需在函数后使用=0就可以了,例如下面这段示例代码:
class Base { public: void f1(){...} // 非虚函数 virtual void f2(){...} // 虚函数,但是不纯 virtual void f3() = 0; // 纯虚函数 }; Base b; // 非法,纯虚函数 f3() 没有具体实现(功能)
上面的 Base 就是一个抽象类(因为它有一个纯虚函数 f3()),所以无法直接使用 Base 实例化对象。正如前文所说,抽象类通常是作为基类使用的,例如下面这段C 语言代码示例:
class Derived : public Base { // 没有 f1(),没问题 // 没有 f2(),没问题 void f3(){...} // 重写 f3() }; Derived d; // 合法, Derived::f3 重写了 Base::f3
Derived 类继承了抽象基类 Base,并且重写了纯虚函数 Base::f3(),因此 Derived 类可以实例化对象 d 使用。注意到派生类 Derived 重写 f3() 时并未显式的使用 virtual 关键字,这是没有问题的,只要保证函数名、参数、返回值都与基类 Base 中的纯虚函数一致,编译器会自动将其识别为虚函数的。
因为派生类 Derived 重写了基类 Base 中的纯虚函数,因此它不再是抽象类,其他继承 Derived 的派生类也不再是抽象类,除非这些派生类定义了自己的纯虚函数。
纯虚函数也可以有功能
纯虚函数也可以有功能基类中的纯虚函数也可以像其他普通函数那样提供一些通用的功能,例如:
void Base::f3(){ cout<< "ok\n"; }
但是要注意,即使纯虚函数 f3() 有自己的功能,基类 Base 仍然是抽象类,还是不能够实例化对象,它的派生类必须重写 f3(),否则该派生类也是抽象类,只不过派生类在重写 f3() 时,可以调用 Base::f3(),例如下面这段C 语言代码示例:
纯虚函数非常有用
void Derived::f3() { ... Base::f3(); }
纯虚函数可以提供抽象类的功能,抽象类则通常提供统一接口的功能,强迫继承它的派生类各自实现符合自己特点的具体功能,并且一定要有这样的功能,这对于设计和架构非常有用。例如,设计师设计了一个汉语翻译程序,他定义了一个基类,该基类中有两个纯虚函数:
class Base { public: virtual string translate_to(string raw) = 0; virtual string translate_from(string raw) = 0; void help() { ... }; };
其中 translate_to() 函数负责将其他外语翻译为汉语,translate_from() 函数负责将汉语翻译为其他外语,因为暂时还不知道具体要实现哪种外语与汉语的翻译,因此这两个函数都是纯虚函数。在接下来的C 语言程序开发中,各种子外语都需要继承 Base,也即必须提供各自的翻译实现,设计师的基本功能要求就成了必须完成的任务。从上面的这个例子可以看出,借助于C 语言的纯虚函数机制,设计师无需再提供详细的功能实现,仅需设计出基本功能要求就可以了。至于非虚函数 Base::help() 函数则可以提供通用的功能,比如输出此程序的帮助信息。
小结稍稍思考下,应该能够发现C 语言中的纯虚函数其实提供了一种“强制”功能——纯虚函数必须被具体实现,才能够实例化对象使用,从文章末尾的例子能够看出这非常有用。这么看来,C 语言中的纯虚函数倒有些类似于“必须实现的接口”了,的确如此,实际上在实际的C 语言程序开发中,如果某个抽象类没有成员变量,它的所有函数均为纯虚函数,那么它就是一组函数接口。
点个关注吧
欢迎在评论区一起讨论,质疑。文章都是手打原创,每天最浅显的介绍C语言、linux等嵌入式开发,喜欢我的文章就关注一波吧,可以看到最新更新和之前的文章哦。
未经许可,禁止转载。
,
免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。文章投诉邮箱:anhduc.ph@yahoo.com