在Visual Studio 2017中如何将类方法作为参数结合Lambda使用?
没问题,我来一步步帮你实现这个需求,用类成员函数指针结合Lambda让代码更灵活,下面是具体的步骤和完整示例:
实现类方法指针的传递与Lambda调用
1. 先定义类成员函数指针的类型
类的非静态成员函数指针必须带上类的作用域,为了避免重复写冗长的类型,我们可以用using给它起个别名:
// 在CMFCApplicationDlg类内部定义 using MethodPtr = void (CMFCApplicationDlg::*)();
这个别名代表CMFCApplicationDlg类中无参数、无返回值的成员函数指针,刚好匹配你的Add_text方法类型。
2. 修改Start_adding方法,接收成员函数指针参数
把Start_adding改成接受一个MethodPtr类型的参数,这样就能灵活传入不同的类方法:
void CMFCApplicationDlg::Start_adding(MethodPtr method_ptr);
3. 在Lambda中调用成员函数指针
因为Lambda捕获了当前对象的this指针,所以需要用(this->*method_ptr)()的语法来调用成员函数指针——这里的->*是专门用于成员指针的调用运算符,括号不能少(否则会因运算符优先级出错)。
完整示例代码
头文件(CMFCApplicationDlg.h)
#pragma once #include <afxwin.h> #include <fstream> // 模拟调度器类(如果你的sched是现成库的对象,直接用就行) class Scheduler { public: template<typename Func> void cron(const char* expr, Func func) { // 这里只是模拟定时逻辑,实际会按 cron 表达式执行func func(); // 临时调用一次用于测试 } }; class CMFCApplicationDlg : public CDialogEx { public: CMFCApplicationDlg(CWnd* pParent = nullptr); enum { IDD = IDD_MFCAPPLICATION_DIALOG }; protected: virtual void DoDataExchange(CDataExchange* pDX); private: Scheduler sched; // 定义成员函数指针的别名 using MethodPtr = void (CMFCApplicationDlg::*)(); void Add_text(); void Another_text(); // 额外加一个测试方法 void Start_adding(MethodPtr method_ptr); // 按钮点击事件示例(需要在资源里绑定) afx_msg void OnBnClickedButtonStart(); DECLARE_MESSAGE_MAP() };
实现文件(CMFCApplicationDlg.cpp)
#include "pch.h" #include "CMFCApplicationDlg.h" CMFCApplicationDlg::CMFCApplicationDlg(CWnd* pParent) : CDialogEx(IDD_MFCAPPLICATION_DIALOG, pParent) {} void CMFCApplicationDlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CMFCApplicationDlg, CDialogEx) ON_BN_CLICKED(IDC_BUTTON_START, &CMFCApplicationDlg::OnBnClickedButtonStart) END_MESSAGE_MAP() void CMFCApplicationDlg::Add_text() { std::ofstream outfile; outfile.open("test.txt", std::ios_base::app); outfile << "text added" << std::endl; } void CMFCApplicationDlg::Another_text() { std::ofstream outfile; outfile.open("test.txt", std::ios_base::app); outfile << "another text added" << std::endl; } void CMFCApplicationDlg::Start_adding(MethodPtr method_ptr) { sched.cron("0 12 * * *", [this, method_ptr]() { // 调用传入的成员函数指针 (this->*method_ptr)(); }); } void CMFCApplicationDlg::OnBnClickedButtonStart() { // 传入Add_text的成员函数指针 Start_adding(&CMFCApplicationDlg::Add_text); // 也可以轻松切换成另一个方法 // Start_adding(&CMFCApplicationDlg::Another_text); }
关键注意点
- 获取成员函数指针时,必须写
&CMFCApplicationDlg::Add_text,不能省略&和类作用域; - Lambda中调用成员指针的语法
(this->*method_ptr)()必须带括号,否则会因运算符优先级问题编译失败; - 如果你需要支持带参数的成员函数,可以修改
MethodPtr的类型,比如using MethodPtrWithParam = void (CMFCApplicationDlg::*)(int);,调用时传入对应参数即可。
内容的提问来源于stack exchange,提问作者maynull
相关产品推荐
相关产品推荐

