取成员函数地址

四哥 2010-12-02 04:17:01
class AClass{
int __cdecl func(int arg) {}
};

要把func成员函数变为普通函数指针有什么方法直接强转没有,而不用定义一个union来取。
...全文
370 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
qq120848369 2010-12-03
  • 打赏
  • 举报
回复
带参数的函数不知道怎么写,坐等人指教.
qq120848369 2010-12-03
  • 打赏
  • 举报
回复
#include <iostream>
using namespace std;

class A
{
public:
void dosth()
{
}
};

template <class T>
union B
{
T point;
void (*p)();
};

int main()
{
union B<void (A::*)()> change;
change.point=&A::dosth;

(change.p)();

return 0;
}
四哥 2010-12-03
  • 打赏
  • 举报
回复
解决了,在VC中可以这样
template<class T>
void *addressof(T t)
{
__asm {
mov eax, t
}
}
addressof(AClass::func);
四哥 2010-12-03
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 we_sky2008 的回复:]

引用 11 楼 lqefn 的回复:
我的意思是要把 成员函数 AClass::func转为普通函数指针int __cdecl (*CommFunc)(void *this, int arg) ,然后可以这样调用 CommFunc(AClassObj, arg);但是强制转换不行,用union转太麻烦。

4,5,6楼的不可以吗?
[/Quote]
把地址转为void*就可以了,要通用,不要对每个类的第个函数写一个转换,类没有统一基类,怎么转?
四哥 2010-12-03
  • 打赏
  • 举报
回复

#include "stdafx.h"
#include <stdarg.h>
#include <windows.h>
#include <locale.h>
#include <stdlib.h>


const int DC_STADCALL = 0, DC_CDECL = 1, DC_QWORD = 2, DC_NOWORD = 4, DC_RET_OBJ = 8, DC_RET_VAL = 16 + 8;
void *gObjectReturnPtr = NULL; // 没有用的

void callfn(void* fn, int args[], int argc, void *optr, int flags, void *buff)
{
int sz = sizeof(int)*argc;
_asm {
mov ecx, argc
mov ebx, args
// push the arguments onto the stack, backwards
a_loop:
cmp ecx,0
jz a_out
mov eax, [ebx + 4*ecx]
push eax
dec ecx
jmp a_loop

a_out:
mov ecx,optr // thiscall calling convention (MS only)
call fn
// Cleanup stack ptr if this was a cdecl call
mov ecx, flags
test ecx,DC_CDECL
jz a_over
add esp,sz
a_over:
test ecx,DC_RET_OBJ
jz a_again
// these cases are peculiar to GCC
cmp ecx,DC_RET_VAL
jl a_skip
mov ebx, gObjectReturnPtr
mov [ebx],eax
mov [ebx+4],edx
jmp a_finish
a_skip:
sub esp,4
a_again:
mov ebx,buff
test ecx,DC_QWORD
jnz a_dbl
mov dword ptr[ebx],eax
jmp a_finish
a_dbl:
fstp qword ptr[ebx]
a_finish:
}
}


class A {
public:
void show(char *msg)
{
printf("msg:%s\n", msg);
}
};


template<class T>
void* addressof(T t)
{
void *retValue;
__asm {
mov eax, t
mov retValue, eax
}
return retValue;
}

class DllModule;

class Function {
private:
void *addr;
int flags;
void *thisPtr;
union CalRet {
__int64 ll;
struct {
int lo;
int hi;
} i2;
char b8[8];
} ret;
public:
Function(void *func, int flag)
{
this->addr = func;
this->flags = flag;
this->thisPtr = NULL;
}
Function(HMODULE hmodule, const char *funcName, int flag)
{
this->addr = (void*)GetProcAddress(hmodule, funcName);
this->flags = flag;
this->thisPtr = NULL;
}
// Function(DllModule &dll, const char *funcName, int flag)
// {
// this->addr = dll.get(funcName);
// this->flags = flag;
// this->thisPtr = NULL;
// }
Function(void *func, void *thisPtr, int flag)
{
this->addr = func;
this->thisPtr = thisPtr;
this->flags = flag;
}
int operator()(int nargs, ...)
{
callfn(addr, &nargs, nargs, thisPtr, flags, ret.b8);
return ret.i2.lo;
}
};

class DllModule {
private:
HMODULE hmodule;
char dllName[128];
public:
DllModule(const char *name)
{
hmodule = LoadLibrary(name);
strncpy(dllName, name, 127);
printf("load library %s\n", name);
}
~DllModule()
{
FreeLibrary(hmodule);
printf("free library %s\n", dllName);
}
void* get(const char *name)
{
return GetProcAddress(hmodule, name);
}
Function cFunc(const char *name, void *thisPtr = NULL)
{
return Function(get(name), thisPtr, DC_CDECL);
}
Function winFunc(const char *name, void *thisPtr = NULL)
{
return Function(get(name), thisPtr, DC_STADCALL);
}
};

int main(int argc, char* argv[])
{
int ret;
DllModule cdll("msvcrt.dll");
ret = cdll.cFunc("printf")(2, "Hello, %s\n", "baby");
printf("ret %d\n", ret);
DllModule user32("user32.dll");
ret = user32.winFunc("MessageBoxW")(4, 0, L"Hello", L"OK", 0);
printf("ret %d\n", ret);
ret = cdll.cFunc("strstr")(2, "Caller has already cleaned the stack", "has");
printf("ret %s\n", ret);
A a;
ret = Function(addressof(A::show), &a, DC_STADCALL)(1, "Class function call");
printf("ret %d\n", ret);
ret = user32.winFunc("FindWindowW")(2, NULL, L"Google - 谷歌浏览器");
printf("ret %d\n", ret);
srand(cdll.cFunc("time")(1, NULL));
int r = rand();
ret = user32.winFunc("ShowWindow")(2, ret, (r % 2) == 0);
printf("r = %d, ret %d\n", r, ret);
return 0;
}
Force200413 2010-12-02
  • 打赏
  • 举报
回复
学习,各种不懂,各种学习。
yiruirui0507 2010-12-02
  • 打赏
  • 举报
回复
#include <iostream>

class base_of_base {
public:
void foo(int i) {
std::cout << "base_of_base::foo(), i: " << i << std::endl;
}
};

class base : public base_of_base {
public:
explicit base(int i) : i_(i) {}

void bar() {
std::cout << "base::bar(), i_: " << i_ << std::endl;
}

virtual void go(std::string s) const = 0;
private:
int i_;
};

class derived : public base {
public:
explicit derived(int i)
: base(i) { }

virtual void go(std::string s) const {
std::cout << "derived::go(), s: " << s << std::endl;
}
};

void
call_go(const base &b) {
void (base::*fn_ptr3)(std::string) const = &base::go;
(b.*fn_ptr3)("3");
}

int
main() {
// case 1
void (derived::*fn_ptr)() = &base::bar;
derived d(1);
(d.*fn_ptr)();

// case 2
void (derived::*fn_ptr2)(int) = &base::foo;
derived d2(2);
(d2.*fn_ptr2)(2);

// case 3
derived d3(3);
call_go(d3);

return (0);
}
yutaooo 2010-12-02
  • 打赏
  • 举报
回复
^_^



// file: csdn.cpp
// g++ csdn.cpp

#include <iostream>

class base_of_base {
public:
void foo(int i) {
std::cout << "base_of_base::foo(), i: " << i << std::endl;
}
};

class base : public base_of_base {
public:
explicit base(int i) : i_(i) {}

void bar() {
std::cout << "base::bar(), i_: " << i_ << std::endl;
}

virtual void go(std::string s) const = 0;
private:
int i_;
};

class derived : public base {
public:
explicit derived(int i)
: base(i) { }

virtual void go(std::string s) const {
std::cout << "derived::go(), s: " << s << std::endl;
}
};

void
call_go(const base &b) {
void (base::*fn_ptr3)(std::string) const = &base::go;
(b.*fn_ptr3)("3");
}

int
main() {
// case 1
void (derived::*fn_ptr)() = &base::bar;
derived d(1);
(d.*fn_ptr)();

// case 2
void (derived::*fn_ptr2)(int) = &base::foo;
derived d2(2);
(d2.*fn_ptr2)(2);

// case 3
derived d3(3);
call_go(d3);

return (0);
}

we_sky2008 2010-12-02
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 lqefn 的回复:]
我的意思是要把 成员函数 AClass::func转为普通函数指针int __cdecl (*CommFunc)(void *this, int arg) ,然后可以这样调用 CommFunc(AClassObj, arg);但是强制转换不行,用union转太麻烦。
[/Quote]
4,5,6楼的不可以吗?
四哥 2010-12-02
  • 打赏
  • 举报
回复
我的意思是要把 成员函数 AClass::func转为普通函数指针int __cdecl (*CommFunc)(void *this, int arg) ,然后可以这样调用 CommFunc(AClassObj, arg);但是强制转换不行,用union转太麻烦。
Metrosexual 2010-12-02
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 skipjack36 的回复:]
C/C++ code

class Foo
{
public:
double One(long inVal);
double Two(long inVal);
};
void main(int argc, char **argv)
{
double (Foo::*funcPtr)(long) = &Foo::One;
Foo aFoo;……
[/Quote]

这个不错
we_sky2008 2010-12-02
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 pengzhixi 的回复:]
唉 如果为虚函数,那么一切都是浮云了。
[/Quote]
恩,
直接通过VPTR求就OK了
pengzhixi 2010-12-02
  • 打赏
  • 举报
回复
唉 如果为虚函数,那么一切都是浮云了。
we_sky2008 2010-12-02
  • 打赏
  • 举报
回复
使用可变参数函数实现强制转换,其实也可以根据普通的函数调用来实现:


#include <iostream>

using namespace std;

class AClass
{
public:
int __cdecl func(int arg)
{
cout<<arg<<endl;
return 0;
}
};

typedef int (__cdecl *t_pf)(AClass *, int);//使用普通函数指针指向成员函数是要多1个参数,即this指针参数

t_pf convert(int other, ...)
{
return (t_pf)*(&other + 1);
}


int main()
{
AClass obj;
int i = 123;
t_pf pf = convert(i, &AClass::func);

obj.func(i);//使用对象调用成员函数
pf(&obj, i);//使用普通函数指针调用成员函数,注意这里的第一个参数就相当于this指针

system("pause");
return 0;
}

we_sky2008 2010-12-02
  • 打赏
  • 举报
回复
使用内联汇编实现强制转换(环境VC6.0)

#include <iostream>

using namespace std;

class AClass
{
public:
int __cdecl func(int arg)
{
cout<<arg<<endl;
return 0;
}
};

typedef int (__cdecl *t_pf)(AClass *, int);//使用普通函数指针指向成员函数是要多1个参数,即this指针参数

t_pf convert(int (__cdecl AClass::*)(int))
{
t_pf i;
__asm
{
mov eax, [ebp + 8]
mov [i], eax
}
return i;
}

int main()
{
AClass obj;
int i = 123;
t_pf pf = convert(&AClass::func);

obj.func(i);//使用对象调用成员函数
pf(&obj, i);//使用普通函数指针调用成员函数,注意这里的第一个参数就相当于this指针

system("pause");
return 0;
}

we_sky2008 2010-12-02
  • 打赏
  • 举报
回复
除了union之外,还可以用指针的指针,可变参数函数,内联汇编等来实现强制转换
我这里只用指针的指针来实现强制类型转换,其他方法楼主可以自己试下,都可以的:

#include <iostream>

using namespace std;

class AClass
{
public:
int __cdecl func(int arg)
{
cout<<arg<<endl;
return 0;
}
};

typedef int (__cdecl *t_pf)(AClass *, int);//使用普通函数指针指向成员函数是要多1个参数,即this指针参数
int (__cdecl AClass::*pf_AClass)(int) = &AClass::func;//定义成员函数指针pf_AClass指向func函数

t_pf pf = *(t_pf *)&pf_AClass;//此处将pf_AClass强制转换为t_pf类型

int main()
{
AClass obj;
int i = 123;

obj.func(i);//使用对象调用成员函数
(obj.*pf_AClass)(i);//使用成员指针调用成员函数
pf(&obj, i);//使用普通函数指针调用成员函数,注意这里的第一个参数就相当于this指针

system("pause");
return 0;
}


skipjack36 2010-12-02
  • 打赏
  • 举报
回复

class Foo
{
public:
double One(long inVal);
double Two(long inVal);
};
void main(int argc, char **argv)
{
double (Foo::*funcPtr)(long) = &Foo::One;
Foo aFoo;
double result = (aFoo.*funcPtr)(2);
return 0;
}
linwendong1982 2010-12-02
  • 打赏
  • 举报
回复
int (AClass::* p)(int) = &AClass::func;
pengzhixi 2010-12-02
  • 打赏
  • 举报
回复
成员函数指针满足不了你的要求?

64,654

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧