C++ 成员函数的宏错误

C++ 成员函数的宏错误,c++,c-preprocessor,C++,C Preprocessor,我正在享受宏的乐趣(不是) #包括 使用名称空间std; #定义定义属性(类型、名称)类型名称\ typedef void(*type_name_t)(CLASS_name*)\ 类型名称ptr类型名称\ void type_name(){(ptr_type_name=&CLASS_name::type_name);}\ 课堂测试 { 公众: #定义类名测试 DEF_属性(int,i_测试); 作废打印() { cout指针类型不是等价的:type\u name\t是函数指针(指向自由函数的指针

我正在享受宏的乐趣(不是)

#包括
使用名称空间std;
#定义定义属性(类型、名称)类型名称\
typedef void(*type_name_t)(CLASS_name*)\
类型名称ptr类型名称\
void type_name(){(ptr_type_name=&CLASS_name::type_name);}\
课堂测试
{
公众:
#定义类名测试
DEF_属性(int,i_测试);
作废打印()
{

cout指针类型不是等价的:
type\u name\t
是函数指针(指向自由函数的指针),而
&Test::type\u name
是指向成员函数的指针。这是编译器告诉您的

无法将指向成员函数的指针转换为简单函数指针的原因是(非静态)成员函数有一个隐藏的
this
参数。您不能通过普通函数指针调用成员函数,因为无法传递
this
参数。您试图通过给
type\u name\t
一个
CLASS\u name*
参数来解释这一点,从概念上讲,这是正确的做法,但C++不是那样的

相反,您需要做的是将delare
键入\u name\t
作为指向成员函数的指针:

typedef void (CLASS_NAME::*type_name_t)();

(未经测试。我希望语法正确;我不会每天使用指向成员函数的指针。)

类型不同

&Test::type\u name
是指向类
Test
的成员函数的指针,而
type\u name\u t
不能包含类
Test
的任何成员函数的地址。它只是指向自由函数(而不是成员函数)的指针

试试这个:

#define CLASS_NAME Test
#define DEF_ATTRIBUTE(type, name) type name;\
    typedef void (CLASS_NAME::*type_name_t)();\
    type_name_t ptr_type_name;\
    void type_name(){( ptr_type_name = &CLASS_NAME::type_name);}\

函数指针不是等价的

void (*type_name_t)(Test*)
不一样

&Test::type_name
函数指针的类型为:指向函数的指针,该函数只接受一个参数,一个测试指针,不返回任何值

您需要的是一个指向成员函数的指针,特别是一个指向不带参数且不返回值的成员函数的指针:

void (Test::*type_name_t) (); // note the empty parameter list!

使用C++中的宏?把宏放在代码中间?我们又来了。如果你不喜欢它,不要张贴。我不是要求一个意见,只是一个答案。我认为这是一个方块宏试图适应一个圆问题。@ Naiija:尽管这里的答案确实回答了这个问题,但问题本身暗示着更大的问题。,即使用蛮力(宏)为了解决一个有一组语言特征的问题,使用谷歌来搜索为什么C预处理器宏是一个不幸的邪恶。在C++中,使用的宏通常是代码气味。@ Skigz:当然,有权衡。这就是为什么人们仍然使用C++的原因。但是,这也是一个TRAD。关闭。如果我能以任何其他“优雅”的方式做我想做的事情,我会::)我应该如何更改
类型名称\u t
以匹配
&测试::类型名称
无效(测试::*类型名称\u t)(测试*)
,尽管我很确定这不是你想要做的。我猜你想更改
类型名称()
method转换为静态方法。@nakiya:编辑答案以显示如何更改
type\u name\t
的声明。@Let\u Me\u:You是对的。如果有指向void*cast的愚蠢函数指针,我会很容易回到家中。@nakiya好吧,这样的转换当然是可能的,问题是函数指针可能会不同大小的成员指针和不同大小的无效指针。更不用说,如果将成员指针和函数指针混合使用,代码会严重崩溃。当然,这并不能解决使用宏的
问题。请尝试在一个类中使用两个
DEF_ATTRIBUTE
s!
&Test::type_name
void (Test::*type_name_t) (); // note the empty parameter list!