/*
* 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;
}
C++中函数指针的运用
最新推荐文章于 2024-07-28 17:17:57 发布