c++中虚函数的一点说明

先帖段代码

 

class A{
public:
    virtual void f1(){puts("A");}
    virtual void f2(){f1();}
};

class B:public A{
public :
    void f1(){puts("B");}
    void f2(){f1();}
};

class C:public A{
public:
    void f1(){puts("C");}
};
int _tmain(int argc, _TCHAR* argv[])
{
    A a; B b; C c;
    a.f2();
    b.f2();
    c.f2();
    printf("\n");

    a.f1(); a.f2();
    a=b;//没有效果?
    a.f1();    a.f2();
    printf("\n");

    class A *pa=NULL;
    pa=&b;
    pa->f1();
    pa->f2();
    pa=&c;
    pa->f1();
    pa->f2();
    printf("\n");
    
    return 0;
}

 

简单说明下,基类A有两个虚函数,B继承了A同时重载了这两个虚函数,C继承了A但只重载了一个虚函数

 

a.f2(), b.f2(), c.f2()这三句结果分别为A B C,因为A的虚表中的函数是A::f1() 和A::f2(),而B的虚表中的函数是B::f1() 和B::f2(),C中的虚表中内容是C::f1() 和A::f2(),这个没什么问题。

 

本段代码难点在接下来的a=b这句,本以为在执行这句赋值语句后a的虚表的内容会发生变化,就是说a.vftable(这是一个指针)会变成b.vftable,但结果a的虚表仍指向原来的内容,指针并未发生改变,这是为什么呢?

在A类中重载A& operator=(A& b) { puts("operator=()");  return b; },发现虽然执行此函数,但a的内容没有因此改变,难道是虚表是不会被赋值运算符改变?

为了验证虚表和普通成员变量不同,我们在A中添加了一个成员变量a,让B中的这个继承而来的变量a和A中的a不同,测试在赋值时A中的a是否因此发生改变,具体修改代码如下

 

class A{
public:
    virtual void f1(){puts("A");}
    virtual void f2(){f1();}
    A(int n=0):a(n){}
protected:
    int a;
    
};

class B:public A{
public :
    void f1(){puts("B");}
    void f2(){f1();}
    B(int n=5):b(n){//a是A的成员变量,虽然被B继承,但仍不能在初始化列表初始化
        a=n+1;
    }
protected:
    int b;
};

 


这样B中的a默认会为6,而A中的a默认为0,执行a=b发现,a中的a已经变成了6,说明这句赋值后a中的成员变量被修改,但虚表指针没有被修改!!!

 

至于为什么赋值不影响虚表,这个应该是可以理解的,属于设计时有意为之,虚表和虚函数的存在是为了多态,如果允许其被修改,则会导致失去多态性

 

 

posted @ 2013-11-20 14:10  IT_cnblogs  阅读(188)  评论(0编辑  收藏  举报