虚函数和重载

面试必考。。。。。

 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;

一句话总结:虚函数是为了实现【多态】; 纯虚函数是为了实现【接口】;

暂时只讨论这么多,后续还会再补充........

posted @ 2013-04-23 23:36  He_LiangLiang  阅读(527)  评论(0编辑  收藏  举报