请指教象这样访问静态成员函数为什么不行?

songshi 2001-05-16 03:36:00
可以通过强制转换访问结构/类中的成员变量.
用这种方法访问静态成员函数可以吗?
请看下面的演示程序:

#include <stdio.h>

class A;
typedef void (A::*fa)();
typedef void (*f)();

class A
{
public:
static void f0(){printf("f0\n");}
static void f1(){printf("f1\n");}
static void f2(){printf("f2\n");}
static void f3(){printf("f3\n");}
static void f4(){printf("f4\n");}
static void f5(){printf("f5\n");}

static f getpfn(int n);
};

f A::getpfn(int n)
{
return (f)(void*)((unsigned long)f0 + n * sizeof(fa));
}

void main()
{
A a;
/*
for(int i = 0; i < 5; i++)
{
f pfn = a.getpfn(i);
(*pfn)();
}
*/

#define P(n) printf("%ld\t", A::f##n); printf("%ld\n", a.getpfn(n));

P(0);
P(1);
P(2);
P(3);
P(4);
P(5);

printf("%ld\t", sizeof(fa)); printf ("%ld\n", sizeof(f));
}

感兴趣的朋友运行一下试试. 请指教为什么不行.
编译时还有一个警告,为什么? 谢谢。

...全文
80 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
songshi 2001-05-17
  • 打赏
  • 举报
回复
关键是不知道有多少个函数需要导出,所以很为难。
songshi 2001-05-17
  • 打赏
  • 举报
回复
好象是没有太好的办法
我再想想吧
谢谢两位
songshi 2001-05-16
  • 打赏
  • 举报
回复
在前面加上这几行中间
typedef void (*SICallback)();
typedef void (CSimComponent::*SIEventHandler)();
typedef void (CSimDialog::*DlgEventHandler)();

songshi 2001-05-16
  • 打赏
  • 举报
回复
#define MAX_THUNKENTRY_COUNT 10

#ifdef _DEBUG
#ifndef MAX_THUNKENTRIES
#define MAX_THUNKENTRIES MAX_THUNKENTRY_COUNT
#endif // MAX_THUNKENTRIES
#endif // _DEBUG

#ifndef MAX_THUNKENTRIES
#error User must define MAX_THUNKENTRIES macro. MAX_THUNKENTRIES value should < 256 && >=0.
#endif // MAX_THUNKENTRIES

#if (MAX_THUNKENTRIES > MAX_THUNKENTRY_COUNT) || (MAX_THUNKENTRIES < 0)
#error MAX_THUNKENTRIES value should <= 256 && >=0.
#endif //(MAX_THUNKENTRIES >= MAX_THUNKENTRY_COUNT) || (MAX_THUNKENTRIES < 0)

#define IMPL_THUNK(n) static void Thunk##n() { switch(m_thunkEntries[n].tteType) { default: case TteNull: ASSERT(FALSE); break; case TteComponent: ASSERT(m_thunkEntries[n].Obj.pComponent != NULL); ASSERT(m_thunkEntries[n].Handler.pfnSiHandler != NULL); (m_thunkEntries[n].Obj.pComponent->*(m_thunkEntries[n].Handler.pfnSiHandler))(); break; case TteDialog: ASSERT(m_thunkEntries[n].Obj.pDialog != NULL); ASSERT(m_thunkEntries[n].Handler.pfnDlgHandler != NULL); (m_thunkEntries[n].Obj.pDialog->*(m_thunkEntries[n].Handler.pfnDlgHandler))(); break; } \ }

#define VALUE_THUNK(n) {TteNull, Thunk##n, NULL, NULL},


class CSIPassbyThunk
{
enum ThunkTableEntryType { TteNull, TteComponent, TteDialog };

struct ThunkTableEntry
{
ThunkTableEntryType tteType;
SICallback pfnCallback;
union tagObj
{
CSimComponent* pComponent;
CSimDialog* pDialog;
}Obj;
union tagHandler
{
SIEventHandler pfnSiHandler;
DlgEventHandler pfnDlgHandler;
}Handler;
};

public:
static SICallback QueryThunk(CSimComponent* pComponent, SIEventHandler pfnSiHandler);
static SICallback QueryThunk(CSimDialog* pDialog, DlgEventHandler pfnDlgHandler);

static ThunkTableEntry m_thunkEntries[MAX_THUNKENTRIES];
static UINT m_nThunkCount;

#if MAX_THUNKENTRIES > 0
IMPL_THUNK(0)
#endif
#if MAX_THUNKENTRIES > 1
IMPL_THUNK(1)
#endif
#if MAX_THUNKENTRIES > 2
IMPL_THUNK(2)
#endif
#if MAX_THUNKENTRIES > 3
IMPL_THUNK(3)
#endif
#if MAX_THUNKENTRIES > 4
IMPL_THUNK(4)
#endif
#if MAX_THUNKENTRIES > 5
IMPL_THUNK(5)
#endif
#if MAX_THUNKENTRIES > 6
IMPL_THUNK(6)
#endif
#if MAX_THUNKENTRIES > 7
IMPL_THUNK(7)
#endif
#if MAX_THUNKENTRIES > 8
IMPL_THUNK(8)
#endif
#if MAX_THUNKENTRIES > 9
IMPL_THUNK(9)
#endif
};

__declspec(selectany) CSIPassbyThunk::ThunkTableEntry CSIPassbyThunk::m_thunkEntries[MAX_THUNKENTRIES] = {
#if MAX_THUNKENTRIES > 0
VALUE_THUNK(0)
#endif
#if MAX_THUNKENTRIES > 1
VALUE_THUNK(1)
#endif
#if MAX_THUNKENTRIES > 2
VALUE_THUNK(2)
#endif
#if MAX_THUNKENTRIES > 3
VALUE_THUNK(3)
#endif
#if MAX_THUNKENTRIES > 4
VALUE_THUNK(4)
#endif
#if MAX_THUNKENTRIES > 5
VALUE_THUNK(5)
#endif
#if MAX_THUNKENTRIES > 6
VALUE_THUNK(6)
#endif
#if MAX_THUNKENTRIES > 7
VALUE_THUNK(7)
#endif
#if MAX_THUNKENTRIES > 8
VALUE_THUNK(8)
#endif
#if MAX_THUNKENTRIES > 9
VALUE_THUNK(9)
#endif
};

请大家再看看我这段愚蠢的代码...
功能是在DLL中, 为类的虚函数的导出做传递工作,有更好的方案吗?
songshi 2001-05-16
  • 打赏
  • 举报
回复
谢谢两位的回答. 我现在用的也是In355Hz兄的代码. 但由于这是在做一个开发框架时遇到的问题. 在一个类中有数目不固定的相似函数. 实现这些函数就很麻烦了, 我实在不想再去构造一个可能大到1000多的数组了, 于是才产生了这个想法.

但在我测试时,发现sizeof(fa) = 4 倒是正确的, 而且各个函数地址也是相差4. 但很奇怪的是它们的入口的顺序和在类中的声明顺序是不一致的. 不解.
111222 2001-05-16
  • 打赏
  • 举报
回复
听课...
In355Hz 2001-05-16
  • 打赏
  • 举报
回复
edyang大侠说的对,就是能得到执行体的大小,也无法保证这样得到的是正确的函数入口,改曾这样吧:
#include <stdio.h>

class A;
typedef void (A::*fa)();
typedef void (*f)();

class A
{
public:
static void f0(){printf("f0\n");}
static void f1(){printf("f1\n");}
static void f2(){printf("f2\n");}
static void f3(){printf("f3\n");}
static void f4(){printf("f4\n");}
static void f5(){printf("f5\n");}
static f f_list[6];

static f getpfn(int n);
};

f A::f_list[6] = {A::f0,A::f1,A::f2,A::f3,A::f4,A::f5};

f A::getpfn(int n)
{
return f_list[n];
}

void main()
{
A a;

for(int i = 0; i < 6; i++)
{
f pfn = a.getpfn(i);
(*pfn)();
}

#define P(n) printf("%ld\t", A::f##n); printf("%ld\n", a.getpfn(n));

P(0);
P(1);
P(2);
P(3);
P(4);
P(5);

printf("%ld\t", sizeof(fa)); printf ("%ld\n", sizeof(f));
}
Edward 2001-05-16
  • 打赏
  • 举报
回复
关于警告:
调用一个类的静态成员函数不需要类的实例,所以有这个警告。

下面的语句明显不对。函数 f0 后面是它的执行代码,而 sizeof(fa) = 4,并不是执行代码体的大小:
return (f)(void*)((unsigned long)f0 + n * sizeof(fa));
所以,这个程序在第一次循环后崩溃。
songshi 2001-05-16
  • 打赏
  • 举报
回复
上面的那个注释不要的。

16,472

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

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