将成员函数指针设置为空闲函数指针
Posted
技术标签:
【中文标题】将成员函数指针设置为空闲函数指针【英文标题】:Set member function pointer to free function pointer 【发布时间】:2020-08-05 15:52:52 【问题描述】:我正在开发一个用 c++ 编码并用 ctypes 包装的简单引擎。我正在研究窗口类,我想让引擎用户能够设置绘制和更新功能。我有以下代码:
window.h
#pragma once
#include <GL/glew.h>
#include <GLFW/glfw3.h>
class window
public:
GLFWwindow* wnd;
window(int width, int height, const char* title);
void close();
void update();
void (window::*draw)();
void setDrawFunction(void (window::*)());
void setUpdateFunction(int*);
;
window.cpp
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include "window.h"
void default_draw()
glClear(GL_COLOR_BUFFER_BIT);
void default_update()
window::window(int width, int height, const char* title)
glfwWindowHint(GLFW_SAMPLES, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_COMPAT_PROFILE, GL_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
wnd = glfwCreateWindow(width, height, title, NULL, NULL);
if (wnd == NULL) glfwTerminate(); return;
glfwMakeContextCurrent(wnd);
if (glewInit() != GLEW_OK)
glfwTerminate();
return;
setDrawFunction((void)(window::*)()default_draw);
void window::close()
glfwDestroyWindow(this->wnd);
void window::update()
default_update();
void window::setDrawFunction(void (window::*fnptr)())
draw = fnptr;
这不起作用。我是否遗漏了一些明显的东西,或者不可能以这种方式完成。如果是这样,我有什么办法可以做到这一点?我所需要的只是能够过载功能,所以我可以在 python 中使用 ctypes 来实现。
我得到的错误: 109 调用前的表达式必须有函数(指针)类型 29 表达式预期 18 应为“)”
【问题讨论】:
default_draw
不是成员函数。您必须添加显式 C 转换 (void)(window::*)()
才能调用 setDrawFunction
compile 的事实很好地表明您没有正确使用它。你需要给它一个window
成员函数。
问题是,我仍然需要以某种方式覆盖类之外的绘制函数。
您可能有兴趣了解std::function
。
对不起,标题不是实际的。现在已更正,问题是一样的。我会立即发布它的更正版本和错误
如果您仍然想要一个面向对象的解决方案同时与 C(和 ctypes)兼容,请考虑使用 void(member*)
函数而不是 void()
。然后draw函数可以用draw(this);
调用draw函数。
【参考方案1】:
使用window
的成员函数指针作为成员变量是不合适的。
我可以考虑以下选项来解决这个问题。
选项 1
将draw
设为非成员函数指针。
void (*draw)();
void setDrawFunction(void (*func)());
选项 2
将draw
设为std::function
std::function<void()> draw;
void setDrawFunction(std::function<void()> func);
选项 3
使用单独的类/接口进行绘图。
std::unique_ptr<DrawingAgent> draw;
void setDrawingAgent(std::unique_ptr<DrawingAgent> agent);
在哪里
class DrawingAgent
public:
virtual void draw(window*); // Draw in given window.
;
在上述选项中,我建议使用选项 3。它将应用程序的 窗口 方面与 绘图 功能清晰地分开。
【讨论】:
实际上我使用了@FrancoisAndrieux 推荐给我的选项 1,但感谢您的回复以上是关于将成员函数指针设置为空闲函数指针的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 C++ lambda 将成员函数指针转换为普通函数指针以用作回调
C++:将派生指针转换为 void 指针,然后转换为抽象指针,并访问成员函数