C++中函数指针的运用

/*
 * class_pointer.cxx
 *
 *  Created on: 2012-9-15
 *      Author: Jesse Meng
 */
 
 
#include <iostream>
using namespace std;
class Base {
public:
    void foo1(void){cout<<"foo1"<<endl;}
    void foo2(void){cout<<"foo2被调用啦,mem2的值是"<<this->mem2<<"!"<<endl;}
    virtual void foo3(void){cout<<"foo3"<<endl;}
    virtual void foo4(void){cout<<"foo4"<<endl;}
    virtual void foo5(void){cout<<"foo5"<<endl;}
 
    Base(int i){
        cout<<"cons"<<endl;
        this->f=&Base::foo2;
        this->mem1=1.0;
        this->mem2=i;
    }
    ~Base(){
        cout<<"des"<<endl;
    }
 
    double mem1;
    int mem2;
    void (Base::*f)(void);
};
 
void test(){cout<<"test函数被调用啦!"<<endl;}
int main(int argc, char **argv) {
    //这个例子不涉及继承的情况啦!!!!!
 
 
    Base *b = new Base(1);
    Base *b2 = new Base(2);
    //声明的两个实例的位置
    cout<<"第一个实例的地址是: "<<b<<endl<<"第二个实例的地址是: "<<b2<<endl;
    //对成员取地址,&后加不加括号都一球样
    cout<<"第一个实例mem1成员的地址是: "<<&b->mem1<<endl
            <<"第一个实例mem2成员的地址是: "<<&b->mem2<<endl
            <<"第一个实例f成员的地址是: "<<&b->f<<endl;
    cout<<"第二个实例mem1成员的地址是: "<<&(b2->mem1)<<endl
            <<"第二个实例mem2成员的地址是: "<<&(b2->mem2)<<endl
            <<"第二个实例f成员的地址是: "<<&b2->f<<endl;
    //再看下函数的地址,下面的输出回事1\n1,这是不对滴
    //
    void (Base::*fad)(void)=&Base::foo1;
    cout<<"前面这个是错的"<<fad<<"| foo1的地址 "<<hex<<*(unsigned *)&fad<<endl;
    fad=&Base::foo2;
    cout<<"前面这个是错的"<<fad<<"| foo2的地址 "<<hex<<*(unsigned *)&fad<<endl;
    fad=&Base::foo3;
    cout<<"前面这个是错的"<<fad<<"| foo3的地址?! "<<hex<<*(unsigned *)&fad<<endl;
    fad=&Base::foo4;
    cout<<"前面这个是错的"<<fad<<"| foo4的地址?! "<<hex<<*(unsigned *)&fad<<endl;
    fad=&Base::foo5;
    cout<<"前面这个是错的"<<fad<<"| foo5的地址?! "<<hex<<*(unsigned *)&fad<<endl;
    cout<<"类中的函数指针演示-----------------------"<<endl;
    /*---------------下面来演示实例中的函数指针和类中方法是如何配合滴----------------------*/
    //这是最普通的例子,木啥好说的
    void (*t) ( )=test;
    t();
    //回顾一下类中的函数指针    void (Base::*f)(void);
    (b->*b->f)();
    //下面的调用过程可以这样来理解
    //b2->f即通过b2获取实例中的函数指针,该指针指向类的方法
    //需要通过一个实例来触发,前面的b即此时的实例
    //所以此时输出的mem2的值为前面那个b中的值,即1
    (b->*b2->f)();
    (b2->*b->f)();
    (b2->*b2->f)();
    //前面的描述可以通过下面的代码来理解
    void (Base::*f2)(void)=NULL;
    f2=b2->f;
    (b->*f2)();
    cout<<"外部的函数指针演示-----------------------"<<endl;
    /*---------------下面来演示外部的函数指针和类中方法是如何配合滴----------------------*/
    //foo1,foo2调用方法和前面的类似
    void (Base::*foo)(void) =&Base::foo1;
    (b->*foo)();
    cout<<"foo1的地址是: "<<hex<<(&Base::foo1)<<"    "<<*(unsigned *)&foo<<endl;
    foo=&Base::foo2;
    (b->*foo)();
    cout<<"foo2的地址是: "<<hex<<(&Base::foo2)<<"    "<<(unsigned *)&foo<<endl;
    //foo3,foo4的地址获取方法
    unsigned int offset=0;
    foo=&Base::foo3;
    offset=*(unsigned *)&foo;
    cout<<"foo3(虚)方法的偏移量(未修正) : "<<offset<<endl;
    //我也不清楚三个虚方法的偏移量为1,5,9?!!!!!
    //这里仅仅是修正一下
    offset/=4;//1/4
    //调用foo3方法
    (b->*foo)();
    //通过foo2来确定,用虚表加偏移地址然后调用的一致性
    void (Base::*foo2)(void)=0;
    //不带继承的情况下实例首地址存放虚表指针,可用"*(unsigned**)b+偏移量"的形式获取
    foo2=*((void (Base::**)(void))(*(unsigned**)b+ offset));
    cout<<"!!!!"<<endl;
    (b->*foo2)();
    cout<<"foo3的地址是: "<<hex<<*(unsigned *)&foo<<"    "<<*(unsigned**)b+offset<<endl;
 
 
    foo=&Base::foo4;
    offset=*(unsigned *)&foo;
    cout<<"foo4(虚)方法的偏移量(未修正) : "<<offset<<endl;
    offset/=4;//5/4
    (b->*foo)();
    cout<<*(unsigned *)&foo<<endl;
    foo2=*((void (Base::**)(void))(*(unsigned**)b+ offset));
    (b2->*foo2)();
    cout<<"foo4的地址是: "<<hex<<*(unsigned *)&foo<<"    "<<*(unsigned**)b2+offset<<endl;
 
 
    foo=&Base::foo5;
    offset=*(unsigned *)&foo;
    cout<<"foo5(虚)方法的偏移量(未修正) : "<<offset<<endl;
    offset/=4;//9/4
    (b->*foo)();
    cout<<*(unsigned *)&foo<<endl;
    foo2=*((void (Base::**)(void))(*(unsigned**)b+ offset));
    (b2->*foo2)();
    cout<<"foo5的地址是: "<<hex<<*(unsigned *)&foo<<"    "<<*(unsigned**)b2+offset<<endl;
 
    delete b;
    //b->~Base();
    delete b2;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值