虚函数和重载
面试必考。。。。。
1 #include <stdio.h> 2 class CBase 3 { 4 public: 5 virtual void f(int x) 6 { 7 printf("CBase::f 函数打印:整数%d\n",x); 8 } 9 10 void g(float x) 11 { 12 printf("CBase::g 函数打印:浮点小数%f\n",x); 13 } 14 }; 15 16 // 继承类 CDerived 17 class CDerived:public CBase 18 { 19 public: 20 void f(int x) 21 { 22 printf("CDerived::f 函数打印:整数%d\n",x); 23 } 24 public: 25 26 void g(float x) 27 { 28 printf("CDerived:g 函数打印:浮点小数%f\n",x); 29 } 30 }; 31 32 33 void main() 34 { 35 36 CDerived DerivedObj; 37 DerivedObj.f(3); 38 DerivedObj.g(6.0f); 39 40 CBase* pBaseObj = &DerivedObj; 41 pBaseObj->f(3); // 此处是指针访问 42 pBaseObj->g(6.0f); 43 }
输出结果为: CDerived::f 函数打印:整数3 CDerived:g 函数打印:浮点小数6.000000 CDerived::f 函数打印:整数3 CBase::g 函数打印:浮点小数6.000000
如果将继承类对象转换为基类对象去调用 f 和 g ,就不一定调用继承类本身的函数。因为基类CBase 的函数 f 为 virtual 虚函数,而继承类 CDerived 又重载了该函数,于是基类的函数 f 【被覆盖】掉,从而 CBase 类的函数实际是 CDerived::f 和 CBase::g。所以,利用转换为基类的对象 *pBaseObj 调用 f函数,仍然是继承类本身定义的函数;但调用 g 函数,则是基类的 g 函数,而不是继承类本身的函数g。这种调用是需要提防的,可能产生混乱。
由此可见,如果一个类的函数希望做的灵活一些,允许继承类的重载函数修改它,最好将它声明为 virtual 虚函数。一个函数一经声明为 virtual 函数,它在继承类中的重载函数,也是虚函数,不必再用virtual 进行修饰。
此外,如果在虚函数的声明之后加上 "=0" 的标记,函数就成为纯虚函数。一个类包含纯虚函数的定义,该类称为抽象类。抽象类不能创建对象,作为继承类的【接口】规范,要求继承类必须提供一个纯虚函数的具体实现,否则产生编译错误。
如下是纯虚函数的一般定义:
virtual 函数返回值类型 函数名( 参数列表 ) =0;
一句话总结:虚函数是为了实现【多态】; 纯虚函数是为了实现【接口】;
暂时只讨论这么多,后续还会再补充........