C++11 探究虚函数

#include<iostream>
using namespace std;
void aaa(){
    cout<<"aa";
}
int main(){
    class a{
    public:
        int a=10;
        int b=4;
        void func1(){
            cout<<"func1 from a"<<endl;
        }
        void func2(){
            cout<<"func2 from a without param"<<endl;
        }
        virtual void func3(){
            cout<<"func3 from a"<<endl;
        }
        virtual void func4(){
            cout<<"func4 from a"<<endl;
        }
    };
    class b:public a{
    public:
        virtual void func1(){
            cout<<"func1 from b"<<endl;
        }
        virtual int func2(int a){
            cout<<"func2 from b with param a"<<a<<endl;
            return 1;
        }
        virtual void func3(){
            cout<<"func3 from b"<<endl;
        }
        virtual void func5(){
            cout<<"func5 from b"<<endl;
        }
    };
    a obj1;
    b obj2;
    obj1.func1();
    obj2.func1();
    obj1.func4();

    obj1.func2();
    obj2.func2(10);     //这两个例子都是重载,最大的一个特点就是可以改变参数列表,也可以改变返回值
    obj1.func4();
    /*

重写是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变。即外壳不变,核心重写!

重写的好处在于子类可以根据需要,定义特定于自己的行为。 也就是说子类能够根据需要实现父类的方法。

*/
    //我们主要看看虚函数和重写的区别
    //虚函数其实也是重写的一种
    //那么虚函数和重写最大的一个区别在哪里呢
    /*
        考虑一个情况
        在java中,线程的模型是,用户自己继承一个系统的thread类,然后用户通过重写这个类的run方法,动态调用
        例如:
        class my_thread : Thread{..实现..};
        list<thread>.push_back( my_thread(..) );

        如果我们只是单纯的重写,而不设置为virtual,会是什么效果呢?
    */
    a *obj3=new b;      //b类假设是我们重写完成的类,现在需要运行这个类
    obj3->func1();      //它实际上这里是调用的基它实际上这里是调用的基类的func1,因为他是a类型【基类类型】的指针,虽然他指向的是b对象
    //这就不能达到,我们在程序运行的时候,写了一个新类,指针指过来,运行的目的了
    //唯一的解决办法就是把这个函数声明成为virtual虚函数
    obj3->func3();      //因为func3是虚函数,他会去虚函数表里面查看,确定运行的是b的func3()
    //因此,虚函数如果要使用,就要使用指针,因为只有指针才能实现基类指针指向派生类对象的操作
    obj3->func4();

    cout<<"------------------------------------------"<<endl;
    //2。探究虚函数表
    //虚函数表的解释网上有很多,就是在类的第一个字节那里存放了一个虚函数表的地址,是一个“函数指针的数组”
    typedef void(*pfun)(void);                          //定义一个void(void)型的函数指针
   
    void *p2=*(int***)obj3;                             //访问第一个虚函数
    p2=*(int**)p2;
    ((pfun)p2)();                                       //访问函数

          p2=*(int***)obj3+1;                           //访问下一个虚函数
    p2=*(int**)p2;                              
    ((pfun)p2)();                                       //访问函数

          p2=*(int***)obj3+2;                           //访问下一个虚函数
    p2=*(int**)p2;                              
    ((pfun)p2)();                                       //访问函数

          p2=*(int***)obj3+3;                           //访问下一个虚函数
    p2=*(int**)p2;                              
    ((pfun)p2)();                                       //访问函数

          p2=*(int***)obj3+4;                           //访问下一个虚函数
    p2=*(int**)p2;                              
    ((pfun)p2)();                                       //访问函数


    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值