/*
类 函数声明
*/
class Base;
class Base1;
class Base2;
class TestClass;
/*
PFThisCall1 参数个数固定,则类stdcall方式编译 但是this指针则由ECX存放
(int parm1)
*/
typedef void (__stdcall *PFThisCall1)(int parm1);
/*
PFThisCall2 参数个数不固定,则类cdecl方式编译 this指针会作为形参传递
(TestClassFirst* pThis,int parmCount,int parm1,...)
*/
typedef void (__cdecl *PFThisCall2)(TestClass* pThis,int parmCount,int parm1,...);
/*
PFunc1代表一个参数的函数
(TestClassFirst* pThis)
*/
typedef void (__stdcall *PFunc1)(TestClass* pThis);
/*
PFunc2代表两个参数的函数
(TestClassFirst* pThis,int parm1)
*/
typedef void (__stdcall *PFunc2)(TestClass* pThis,int parm1);
/*
PFunc3代表三个参数的函数
(TestClassFirst* pThis,int parm1,int parm2)
*/
typedef int (__stdcall *PFunc3)(TestClass* pThis,int parm1,int parm2);
//类函数指针 原本就是__stdcall函数
typedef void ( __stdcall TestClass::*PTestClassFunc1)();
typedef void ( __stdcall TestClass::*PTestClassFunc2)(int parm1);
typedef int ( __stdcall TestClass::*PTestClassFunc3)(int parm1,int parm2);
/*
这个数据结构主要是为了方便:
类函数地址、普通函数地址与数值之间的转化
主要利用联合体共享内存的特征
*/
typedef unsigned long Addr32;
typedef struct
{
unsigned long lAddr;
unsigned long hAddr;
} Addr64;
typedef union _FuncPtr
{
Addr64 addr64; //64位地址
Addr32 addr32; //32位地址
//普通函数指针
PFunc1 pFunc1;
PFunc2 pFunc2;
PFunc3 pFunc3;
//特殊指针
PFThisCall1 pFThisCall1;
PFThisCall2 pFThisCall2;
//类函数指针
PTestClassFunc1 pTestClassFunc1;
PTestClassFunc2 pTestClassFunc2;
PTestClassFunc3 pTestClassFunc3;
} FuncPtr;
/*
GetClassMemberFuncAddr
函数主要是为了根据任意函数地址转化为32位或64位的地址值
memberFunc:任意一个函数(普通函数或者类的函数)
addr:一个32位或64位的保存函数地址值得变量
*/
template<typename ClassMemberFunc,typename MemberFuncAddr>
void GetClassMemberFuncAddr(ClassMemberFunc memberFunc,MemberFuncAddr &addr)
{
union{
ClassMemberFunc memberFunc;
MemberFuncAddr addr;
} converter;//定义共享内存变量
converter.memberFunc=memberFunc;
addr=converter.addr;
};
class Base
{
public:
Base();
~Base();
public:
virtual void __stdcall Func1();
};
class Base1: public Base
{
public:
Base1();
~Base1();
public:
virtual void __stdcall Func1();
virtual void __stdcall Func2(int param1);
};
class Base2: public Base
{
public:
Base2();
~Base2();
public:
virtual int __stdcall Func3(int param1,int parm2);
};
class TestClass:public Base1,public Base2
{
public:
TestClass();
~TestClass();
private:
int m_intVal;
/*
thiscall声明的类函数 其this指针不一定是在函数形参中 得看函数参数个数
参数个数固定,则按stdcall方式编译
参数个数不固定,则按cdecl方式编译
*/
public:
//测试虚函数
//Base2 Func3重写
int __stdcall Func3(int parm1,int parm2);
//TestClass
virtual void __stdcall Func4();
virtual void __stdcall Func5(int parm1);
virtual int __stdcall Func6(int parm1,int parm2);
public:
//测试c++默认thiscall编译的函数
void ThisCall1(int parm1); //参数固定 用stdcall编译 无this形参 ecx保存this
void ThisCall2(int parmCount,...);//参数不固定 用cdecl编译 this指针是第一个形参
public:
void __stdcall Func7();
void __stdcall Func8(int parm1);
int __stdcall Func9(int parm1,int parm2);
private:
void __stdcall PrivateFunc1();
};
#include "stdafx.h"
#include "TestClass.h"
Base::Base()
{
}
Base::~Base()
{
}
void Base::Func1()
{
long pointerValue=(long)this;
printf("Base::Func1 Run:\n this pointer=%x\n",pointerValue);
}
/
Base1::Base1()
{
}
Base1::~Base1()
{
}
void Base1::Func1()
{
long pointerValue=(long)this;
printf("Base1::Func1 Run:\n this pointer=%x\n",pointerValue);
}
void Base1::Func2(int parm1)
{
long pointerValue=(long)this;
printf("Base1::Func2 Run:\n this pointer=%x,parm1=%d\n",pointerValue,parm1);
}
Base2::Base2()
{
}
Base2::~Base2()
{
}
int Base2::Func3(int parm1,int parm2)
{
long pointerValue=(long)this;
printf("Base2::Func3 Run:\n this pointer=%x,parm1=%d,parm2=%d\n",pointerValue,parm1,parm2);
return parm1+parm2;
}
TestClass::TestClass()
{
m_intVal=0;
}
TestClass::~TestClass()
{
}
int TestClass::Func3(int parm1,int parm2)
{
long pointerValue=(long)this;
printf("Func3 Run:\n this pointer=%x,parm1=%d,parm2=%d\n",pointerValue,parm1,parm2);
return parm1;
}
void TestClass::Func4()
{
int temp=m_intVal;
m_intVal-=1;
long pointerValue=(long)this;
printf("Func4 Run:\n this pointer=%x,m_intVal=%d\n m_intVal-=1\n m_intVal=%d\n",pointerValue,temp,m_intVal);
}
void TestClass::Func5(int parm1)
{
int temp=m_intVal;
long pointerValue=(long)this;
m_intVal=parm1;
printf("Func5 Run:\n this pointer=%x,m_intVal=%d,parm1=%d\n m_intVal=parm1=%d\n",pointerValue,temp,parm1,m_intVal);
}
int TestClass::Func6(int parm1,int parm2)
{
int temp=m_intVal;
long pointerValue=(long)this;
m_intVal=parm1-parm2;
printf("Func6 Run:\n this pointer=%x,m_intVal=%d,parm1=%d,parm2=%d\n return value m_intVal=parm1-parm2=%d\n",pointerValue,temp,parm1,parm2,m_intVal);
return m_intVal;
}
void TestClass::Func7()
{
int temp=m_intVal;
m_intVal+=1;
long pointerValue=(long)this;
printf("Func7 Run:\n this pointer=%x,m_intVal=%d\n m_intVal+=1\n m_intVal=%d\n",pointerValue,temp,m_intVal);
}
void TestClass::Func8(int parm1)
{
int temp=m_intVal;
long pointerValue=(long)this;
m_intVal-=parm1;
printf("Func8 Run:\n this pointer=%x,m_intVal=%d,parm1=%d\n m_intVal-=parm1\n m_intVal=%d\n",pointerValue,temp,parm1,m_intVal);
}
int TestClass::Func9(int parm1,int parm2)
{
int temp=m_intVal;
long pointerValue=(long)this;
m_intVal=parm1+parm2;
printf("Func9 Run:\n this pointer=%x,m_intVal=%d,parm1=%d,parm2=%d\n return value m_intVal=parm1+parm2=%d\n",pointerValue,temp,parm1,parm2,m_intVal);
return m_intVal;
}
void TestClass::ThisCall1(int parm1)
{
int temp=m_intVal;
long pointerValue=(long)this;
m_intVal+=parm1;
printf("ThisCall1 Run:\n this pointer=%x,m_intVal=%d,parm1=%d\n m_intVal+=parm1\n m_intVal=%d\n",pointerValue,temp,parm1,m_intVal);
}
void TestClass::ThisCall2(int parmCount,...)
{
int temp=m_intVal;
va_list vaptr;
int i,j;
va_start(vaptr,parmCount);
for(i=0; i<parmCount;i++)
{
j= va_arg(vaptr,int);
m_intVal +=j;
}
va_end(vaptr);
long pointerValue=(long)this;
printf("ThisCall2 Run:\n this pointer=%x,m_intVal=%d,parmCount=%d,...\n m_intVal+=parm1+...\n m_intVal=%d\n",pointerValue,temp,parmCount,m_intVal);
}
void TestClass::PrivateFunc1()
{
long pointerValue=(long)this;
printf("PrivateFunc1 Run:\n this pointer=%x",pointerValue);
}
//执行文件
#include "stdafx.h"
#include "TestClass.h"
int _tmain(int argc, _TCHAR* argv[])
{
/*
本程序主要功能:
1.测试类函数获取
2.将获取的类函数执行
3.该方法对于虚函数会存在问题
*/
/*
程序初始条件
*/
TestClass *pTestObj=new TestClass;//提供this指针对象
TestClass *pTestObjNew=new TestClass;//提供this指针对象
FuncPtr funcPtr;
/*
(一)构造函数测试
*/
/*
(二)thiscall函数测试
*/
/*
ThisCall1函数参数个数一定 参照stdcall 但无this指针的形参 ecx保存this指针
*/
GetClassMemberFuncAddr(&TestClass::ThisCall1,funcPtr.addr32);
__asm
{
mov ecx, dword ptr [pTestObj]
}
funcPtr.pFThisCall1(-10);
/*
ThisCall2函数参数个数不定 参照cdecl 但this指针是函数第一个形参
*/
GetClassMemberFuncAddr(&TestClass::ThisCall2,funcPtr.addr32);
funcPtr.pFThisCall2(pTestObj,3,9,50,62);
/*
(三)虚函数测试
主要验证虚函数表的获取
类对象的第一四字节 存放第一个父类和自身的所有虚函数地址存储空间(连续的一片小空间)的地址
第二四字节 存放第二个父类所有虚函数地址存储空间(连续的一片小空间)的地址
所以类对象的首地址就相当于一个二维指针,包含了所有虚函数表,二每张表又包含了多个函数地址
(vfptr) Func1
Func2
Func4
Func5
Func6
(vfptr) Func1
Func3
Func3函数不能正常运行 说明虚函数的地址 并不是靠函数名就能总是正确
*/
//Func1
GetClassMemberFuncAddr(&Base1::Func1,funcPtr.addr32);
funcPtr.pFunc1(pTestObj);//pTestObj传递this指针
//Func2
GetClassMemberFuncAddr(&TestClass::Func2,funcPtr.addr32);
funcPtr.pFunc2(pTestObj,678);//pTestObj传递this指针
//Func3此处 运行不正确 会运行Base1::Func2 总感觉跟虚函数的调用方式有关 不明白是怎么回事????
GetClassMemberFuncAddr(&TestClass::Func3,funcPtr.addr32);
funcPtr.pFunc3(pTestObj,-120,321);
Addr32 memObjAddr=(Addr32)pTestObj;//对象存放位置的前四个字节就是vfptr虚表指针
Addr32 **vfptr=(Addr32 **)(memObjAddr);
//虚函数表1执行
funcPtr.addr32=vfptr[0][0];//Base1 Func1
funcPtr.pFunc1(pTestObj);
funcPtr.addr32=vfptr[0][1];//Base1 Func2
funcPtr.pFunc2(pTestObj,12);
funcPtr.addr32=vfptr[0][2];//TestClass Func4
funcPtr.pFunc1(pTestObj);
funcPtr.addr32=vfptr[0][3];//TestClass Func5
funcPtr.pFunc2(pTestObj,21);
funcPtr.addr32=vfptr[0][4];//TestClass Func6
funcPtr.pFunc3(pTestObj,13,25);
//虚函数表2执行
funcPtr.addr32=vfptr[1][0];//Base Func1
funcPtr.pFunc1(pTestObj);
funcPtr.addr32=vfptr[1][1];//TestClass Func3
funcPtr.pFunc3(pTestObj,12,13);
/*
(四)类函数测试
*/
//Func7
GetClassMemberFuncAddr(&TestClass::Func7,funcPtr.addr32);
funcPtr.pFunc1(pTestObj);//pTestObj传递this指针
//Func8
GetClassMemberFuncAddr(&TestClass::Func8,funcPtr.addr32);
funcPtr.pFunc2(pTestObjNew,678);//pTestObj传递this指针
//Func9
GetClassMemberFuncAddr(&TestClass::Func9,funcPtr.addr32);
funcPtr.pFunc3(pTestObjNew,-120,321);//pTestObj传递this指针
delete pTestObj;
return 0;
}
附注:"stdafx.h"包含以下文件:
#include <stdarg.h>
感悟:C++永远都是学不明白的语言 太复杂了 难学 难懂
问题:(1)红色注记部分运行原理还不明白 看看有没有谁能给我指点下????