C++:非成员函数的定义/声明的位置
C++: location of definition/declaration of non-member function
我有一个类Myclass:
在Myclass.h文件中:
class{
private:
int sd;
int sd2;
public:
void func(int sd, short op, void *ptr);
void start();
};
在Myclass.cpp文件中:
void Myclass::start(){
struct arg_t *arg = (struct arg_t *)malloc(sizeof(struct arg_t));
....
event_set(ev, sd, EV_READ, call_func, arg ); //this is a library API, which trigger the callback of call_func(sd, op, arg);
}
void Myclass::func(int sd, short op, void *ptr)){
...
if(some_conditions){
struct arg_t *arg = (struct arg_t *)malloc(sizeof(struct arg_t))
....
event_set(ev, sd2, EV_READ, call_func, arg );
.....
}
...
}
在main.cpp 中
int main(){
Myclass obj;
....
obj.start();
....
}
在start()中,event_set需要一个void(*func)()
类型的函数作为参数,但func()是void Myclass::(*func)()
类型的,所以我定义了一个新函数,如下所示(代码不正确,但只是显示了我的期望):
void call_func(int sd, short op, void *ptr){
Myclass::func(int sd, short op, void *ptr);
}
然而,我不知道在哪里delcare和定义call_func()
,以便Myclass::start()
可以使用call_func
作为参数,call_func()
可以调用Myclass::func()
这是一个已知的问题。由于指向类成员的指针不是常规指针,因此不能在天真回调中使用类成员函数,因为天真回调需要一个简单的函数指针。
一个解决方案是制作一个回调函数static
,通常是private
,并使用回调参数调用相应的类函数。在您的情况下,它看起来如下:
class C {
private:
int sd;
static void call_func(int sd, short op, void* ptr) {
C* obj = static_cast<C*>(ptr);
obj->func(sd, op);
}
public:
void func(int sd, short op);
void start() {
event_set(ev, sd, EV_READ, &call_func, this);
}
};
编辑
修复了混乱的start()
和func()
。
我不知道在哪里delcare和定义
call_func()
,以便Myclass::start()
可以使用call_func
作为参数,call_func()
可以调用Myclass::func()
您可以将这一切放在Myclass.cpp文件中,位于Myclass::start()的定义之上
#include <Myclass.h>
void call_func(int sd, short op, void *ptr){
Myclass::func(int sd, short op, void *ptr);
}
void Myclass::start(){
event_set(ev, sd, EV_READ, call_func, NULL ); //this is a library API, which trigger the callback of call_func(sd, op, NULL);
}
void Myclass::func(int sd, short op, void *ptr)){
...
...
}
还有一件事,对于回调函数,void* ptr
是如何传递指向回调函数将使用的某些数据的指针。如果你不需要这样的东西,那么你就不需要调用一个非静态成员函数作为回调,你可以简化事情。但是,要按照您描述的方式调用非静态成员函数,您需要一个对象来调用它,这就是您将传递的void *ptr
:
// Myclass.h
class Myclass {
private:
int sd;
public:
void func(int sd, short op); // no void*
void start();
};
// Myclass.cpp
#include <Myclass.h>
void call_func(int sd, short op, void *ptr){
assert(ptr != NULL);
static_cast<Myclass *>(ptr)->func(int sd, short op); // cast data to 'this' pointer
}
void Myclass::start(){
event_set(ev, sd, EV_READ, call_func, this ); // pass the 'this' pointer as data
}
void Myclass::func(int sd, short op)){
...
...
}
event_set()
的最后一个参数仍然需要用于指向附加结构的指针,因此它不可能是this
您需要以某种方式传递this
,否则就不能调用成员函数,所以如果您有另一个结构,则需要考虑如何传递两者。
另一个结构或指向它的指针是否可以是对象的成员?如果是,则执行该操作并将this
作为void *ptr
传递。
另一种选择是定义一个struct
,仅用于通过回调传递数据:
struct callback_params {
Myclass *c;
other_struct *s;
};
但是,您必须在某个地方创建这个callback_params
结构,使其能够存活足够长的时间,以便回调能够接收它,这可能很棘手。
错误答案
我的旧平板电脑没有加载问题的代码部分正确,我错过了问题的重要部分
离开这里只是为了完整性——也许这可以是util对于其他人
对不起
我不知道你在做什么,但在这种情况下,如果我不需要旧代码的接口,我肯定会选择std::function
。
但如果绝对需要指针的东西,我通常会这样做:
- 在函数中放一个非常丑陋的名字——所以每个人都会知道这是一个"黑客",不是一件好事。例如:
_func_call_wrapper_(...)
- 将带有适当注释的定义放在.cpp文件的顶部,依此类推。例如:
//This is a wrapper neeeded for...
void __func_call_wrappper_(..);
- 最后,在.cpp文件的底部,我定义了函数,当然,有很多关于为什么需要这样做的评论
参考文献:ccpreference
- 如何确保C++函数在定义之前声明(如override关键字)
- 为什么在定义函数之前先声明它
- 为什么我不能在一个类的不同行中声明和定义成员变量?
- Visual Studio中的函数声明和函数定义问题
- C++错误C2600:无法定义编译器生成的特殊成员函数(必须首先在类中声明)
- 如何在标头中声明(或定义)函数的问题
- 程序顶部的声明与定义(最佳实践)
- 类的前向声明之后的类成员函数定义,在类声明之前
- 静态变量声明和定义
- C++ G++ 编译器 - 错误:隐式声明的定义
- C++:错误重定义和先前声明
- 类模板静态数据成员定义/声明/初始化
- 只有一个定义/声明时标头声明变量的多堆定义错误
- OpenCV - Ptr 语法和类定义/声明 - 混淆?
- 如何为非类型模板类的专用化定义声明之外的方法
- 我如何防止静态类成员变量需要两个定义/声明
- 默认定义声明的详细程度不完整
- C++:非成员函数的定义/声明的位置
- 将比较操作符的重载定义/声明为库中的非成员函数
- C++头重新定义/声明混合