C++11 将方法作为参数传递
我已经复习了这篇优秀的文章,但我仍然感到困惑。最终我将有10个行为相似的方法。下面是我已经写过的三个例子:C++11 将方法作为参数传递,c++11,mfc,C++11,Mfc,我已经复习了这篇优秀的文章,但我仍然感到困惑。最终我将有10个行为相似的方法。下面是我已经写过的三个例子: void CChristianLifeMinistryEditorDlg::OnSwapWithChairmanAssignment(UINT nID) { // We need to locate the name for this assignment auto iter = m_mapSwapAssignments.find(nID); if (iter
void CChristianLifeMinistryEditorDlg::OnSwapWithChairmanAssignment(UINT nID)
{
// We need to locate the name for this assignment
auto iter = m_mapSwapAssignments.find(nID);
if (iter != m_mapSwapAssignments.end())
{
// We found it
CChristianLifeMinistryEntry *pReplacement = m_mapSwapAssignments[nID];
CString strExistingName = _T(""), strReplacementName = _T("");
GetDlgItemText(m_iSwapAssignmentSourceID, strExistingName);
CString strPrompt = _T("");
strPrompt.Format(_T("Swap assignments:\n\n%s - %s\n%s - %s\n\nPlease confirm."),
m_pEntry->GetMeetingDateAsString(),
(LPCTSTR)strExistingName,
pReplacement->GetMeetingDateAsString(),
(LPCTSTR)pReplacement->GetChairman());
if (AfxMessageBox(strPrompt, MB_ICONQUESTION | MB_YESNO) == IDYES)
{
strReplacementName = pReplacement->GetChairman();
pReplacement->SetChairman(strExistingName);
SetDlgItemText(m_iSwapAssignmentSourceID, strReplacementName);
SetModified(true);
}
}
}
void CChristianLifeMinistryEditorDlg::OnSwapWithOpenPrayerAssignment(UINT nID)
{
// We need to locate the name for this assignment
auto iter = m_mapSwapAssignments.find(nID);
if (iter != m_mapSwapAssignments.end())
{
// We found it
CChristianLifeMinistryEntry *pReplacement = m_mapSwapAssignments[nID];
CString strExistingName = _T(""), strReplacementName = _T("");
GetDlgItemText(m_iSwapAssignmentSourceID, strExistingName);
CString strPrompt = _T("");
strPrompt.Format(_T("Swap assignments:\n\n%s - %s\n%s - %s\n\nPlease confirm."),
m_pEntry->GetMeetingDateAsString(),
(LPCTSTR)strExistingName,
pReplacement->GetMeetingDateAsString(),
(LPCTSTR)pReplacement->GetOpenPrayer());
if (AfxMessageBox(strPrompt, MB_ICONQUESTION | MB_YESNO) == IDYES)
{
strReplacementName = pReplacement->GetOpenPrayer();
pReplacement->SetOpenPrayer(strExistingName);
SetDlgItemText(m_iSwapAssignmentSourceID, strReplacementName);
SetModified(true);
}
}
}
void CChristianLifeMinistryEditorDlg::OnSwapWithClosePrayerAssignment(UINT nID)
{
// We need to locate the name for this assignment
auto iter = m_mapSwapAssignments.find(nID);
if (iter != m_mapSwapAssignments.end())
{
// We found it
CChristianLifeMinistryEntry *pReplacement = m_mapSwapAssignments[nID];
CString strExistingName = _T(""), strReplacementName = _T("");
GetDlgItemText(m_iSwapAssignmentSourceID, strExistingName);
CString strPrompt = _T("");
strPrompt.Format(_T("Swap assignments:\n\n%s - %s\n%s - %s\n\nPlease confirm."),
m_pEntry->GetMeetingDateAsString(),
(LPCTSTR)strExistingName,
pReplacement->GetMeetingDateAsString(),
(LPCTSTR)pReplacement->GetClosePrayer());
if (AfxMessageBox(strPrompt, MB_ICONQUESTION | MB_YESNO) == IDYES)
{
strReplacementName = pReplacement->GetClosePrayer();
pReplacement->SetClosePrayer(strExistingName);
SetDlgItemText(m_iSwapAssignmentSourceID, strReplacementName);
SetModified(true);
}
}
}
我想将每个事件处理程序中的代码编码到一个方法中
GetChairman
SetChairman
GetOpenPrayer
SetOpenPrayer
GetClosePrayer
SetClosePrayer
void CChristianLifeMinistryEditorDlg::SwapAssignments(UINT nID, CString(*GetExistingName), void(*SetReplacementName)(CString))
{
// We need to locate the name for this assignment
auto iter = m_mapSwapAssignments.find(nID);
if (iter != m_mapSwapAssignments.end())
{
// We found it
CChristianLifeMinistryEntry *pReplacement = m_mapSwapAssignments[nID];
CString strExistingName = _T(""), strReplacementName = _T("");
GetDlgItemText(m_iSwapAssignmentSourceID, strExistingName);
CString strPrompt = _T("");
strPrompt.Format(_T("Swap assignments:\n\n%s - %s\n%s - %s\n\nPlease confirm."),
m_pEntry->GetMeetingDateAsString(),
(LPCTSTR)strExistingName,
pReplacement->GetMeetingDateAsString(),
(LPCTSTR)pReplacement->(*GetExistingName));
if (AfxMessageBox(strPrompt, MB_ICONQUESTION | MB_YESNO) == IDYES)
{
strReplacementName = pReplacement->(*GetExistingName);
pReplacement->(*SetReplacementName)(strExistingName);
SetDlgItemText(m_iSwapAssignmentSourceID, strReplacementName);
SetModified(true);
}
}
}
我发现生成错误:
如何将这些方法作为参数传递
我看到了另一个我希望可以使用的方法,但问题是被调用的方法是对象的成员。所以它不允许这样做
当前解决方法 目前,我已经实现了几个功能:
CString CChristianLifeMinistryEntry::GetName(SwapAssignment eAssignment)
{
switch (eAssignment)
{
case SwapAssignment::Chairman:
return GetChairman();
case SwapAssignment::Counsellor1:
return GetAuxiliaryCounsellor1();
case SwapAssignment::Counsellor2:
return GetAuxiliaryCounsellor2();
case SwapAssignment::OpenPrayer:
return GetOpenPrayer();
case SwapAssignment::Treasures1:
return GetTreasures1();
case SwapAssignment::Treasures2:
return GetTreasures2();
case SwapAssignment::Living1:
return GetLiving1();
case SwapAssignment::Living2:
return GetLiving2();
case SwapAssignment::ConductorCBS:
return GetCBSConductor();
case SwapAssignment::ReaderCBS:
return GetCBSReader();
case SwapAssignment::ClosePrayer:
return GetClosePrayer();
}
return _T("");
}
// AJT v18.1.6
void CChristianLifeMinistryEntry::SetName(CString strName, SwapAssignment eAssignment)
{
switch (eAssignment)
{
case SwapAssignment::Chairman:
SetChairman(strName);
break;
case SwapAssignment::Counsellor1:
SetAuxiliaryCounsellor1(strName);
break;
case SwapAssignment::Counsellor2:
SetAuxiliaryCounsellor2(strName);
break;
case SwapAssignment::OpenPrayer:
SetOpenPrayer(strName);
break;
case SwapAssignment::Treasures1:
SetTreasures1(strName);
break;
case SwapAssignment::Treasures2:
SetTreasures2(strName);
break;
case SwapAssignment::Living1:
SetLiving1(strName);
break;
case SwapAssignment::Living2:
SetLiving2(strName);
break;
case SwapAssignment::ConductorCBS:
SetCBSConductor(strName);
break;
case SwapAssignment::ReaderCBS:
SetCBSReader(strName);
break;
case SwapAssignment::ClosePrayer:
SetClosePrayer(strName);
break;
}
}
然后,我将我提到的代码稍加调整,移到一个新方法中:
// AJT v18.1.6
void CChristianLifeMinistryEditorDlg::SwapAssignments(UINT nID, SwapAssignment eAssignment)
{
// We need to locate the name for this assignment
auto iter = m_mapSwapAssignments.find(nID);
if (iter != m_mapSwapAssignments.end())
{
// We found it
CChristianLifeMinistryEntry *pReplacement = m_mapSwapAssignments[nID];
CString strExistingName = _T(""), strReplacementName = _T("");
GetDlgItemText(m_iSwapAssignmentSourceID, strExistingName);
CString strPrompt = _T("");
strPrompt.Format(_T("Swap assignments:\n\n%s - %s\n%s - %s\n\nPlease confirm."),
m_pEntry->GetMeetingDateAsString(),
(LPCTSTR)strExistingName,
pReplacement->GetMeetingDateAsString(),
(LPCTSTR)pReplacement->GetName(eAssignment));
if (AfxMessageBox(strPrompt, MB_ICONQUESTION | MB_YESNO) == IDYES)
{
strReplacementName = pReplacement->GetName(eAssignment);
pReplacement->SetName(strExistingName, eAssignment);
if (pReplacement == m_pEntry) // Swapping assignments on same meeting!
SetDlgItemText(IDC_COMBO_OCLM_CBS_READER, strExistingName);
SetDlgItemText(m_iSwapAssignmentSourceID, strReplacementName);
SetModified(true);
}
}
}
现在,我的11个处理程序与此类似:
// AJT v18.1.6
void CChristianLifeMinistryEditorDlg::OnSwapWithCBSReaderAssignment(UINT nID)
{
SwapAssignments(nID, SwapAssignment::ReaderCBS);
}
它起作用了。但我看到我的问题中添加了一条新的注释,并带有一个链接,因此我将看看我是否能取得任何进展。因此,让我们分阶段重构代码 第一阶段: 首先,在通用函数
OnSwapWith
template<typename Function>
void CChristianLifeMinistryEditorDlg::OnSwapWith(Function && function,
UINT nID)
{
// We need to locate the name for this assignment
auto iter = m_mapSwapAssignments.find(nID);
if (iter != m_mapSwapAssignments.end())
{
// We found it
CChristianLifeMinistryEntry *pReplacement = m_mapSwapAssignments[nID];
CString strExistingName = _T(""), strReplacementName = _T("");
GetDlgItemText(m_iSwapAssignmentSourceID, strExistingName);
CString strPrompt = _T("");
strPrompt.Format(_T("Swap assignments:\n\n%s - %s\n%s - %s\n\nPlease confirm."),
m_pEntry->GetMeetingDateAsString(),
(LPCTSTR)strExistingName,
pReplacement->GetMeetingDateAsString(),
(LPCTSTR)pReplacement->GetChairman());
if (AfxMessageBox(strPrompt, MB_ICONQUESTION | MB_YESNO) == IDYES)
{
function();
SetDlgItemText(m_iSwapAssignmentSourceID, strReplacementName);
SetModified(true);
}
}
}
void CChristianLifeMinistryEditorDlg::OnSwapWithChairmanAssignment(UINT nID)
{
auto ChairmanAssignment = [&]() // capture by reference (i.e. &)
{
strReplacementName = pReplacement->GetChairman();
pReplacement->SetChairman(strExistingName);
};
CChristianLifeMinistryEditorDlg::OnSwapWith(ChairmanAssignment, nID);
}
void CChristianLifeMinistryEditorDlg::OnSwapWithOpenPrayerAssignment(UINT nID)
{
auto OpenPrayerAssignment = [&]() // capture by reference (i.e. &)
{
strReplacementName = pReplacement->GetOpenPrayer();
pReplacement->SetOpenPrayer(strExistingName);
};
CChristianLifeMinistryEditorDlg::OnSwapWith(OpenPrayerAssignment, nID);
}
void CChristianLifeMinistryEditorDlg::OnSwapWithClosePrayerAssignment(UINT nID)
{
auto ClosePrayerAssignment = [&]() // capture by reference (i.e. &)
{
strReplacementName = pReplacement->GetClosePrayer();
pReplacement->SetClosePrayer(strExistingName);
};
CChristianLifeMinistryEditorDlg::OnSwapWith(ClosePrayerAssignment, nID);
}
// and similarly other functions can be defined
那么来电方呢
void CChristianLifeMinistryEditorDlg::OnSwapWithChairmanAssignment(UINT nID)
{
auto getter = [](CChristianLifeMinistryEntry * pReplacement)
{ // remove the captures now, since we are getting the state with the pointer
return pReplacement->GetChairman();
};
auto setter = [](CChristianLifeMinistryEntry * pReplacement,
CString const & strExistingName)
{
pReplacement->SetChairman(strExistingName);
};
CChristianLifeMinistryEditorDlg::OnSwapWith(getter, setter, nID);
}
最终工作代码 11个菜单事件处理程序类似于:
void CChristianLifeMinistryEditorDlg::OnSwapWithChairmanAssignment(UINT nID)
{
auto getter = [](CChristianLifeMinistryEntry * pReplacement)
{
return pReplacement->GetChairman();
};
auto setter = [](CChristianLifeMinistryEntry * pReplacement,
CString & strExistingName)
{
pReplacement->SetChairman(strExistingName);
};
CChristianLifeMinistryEditorDlg::OnSwapWith(getter, setter,
nID, IDC_COMBO_OCLM_CHAIRMAN);
}
模板化函数现在看起来像:
template<typename GetterFunction, typename SetterFunction>
void CChristianLifeMinistryEditorDlg::OnSwapWith(GetterFunction && getter,
SetterFunction && setter,
UINT nID,
UINT nReplacementCtrlID)
{
// We need to locate the name for this assignment
auto iter = m_mapSwapAssignments.find(nID);
if (iter != m_mapSwapAssignments.end())
{
// We found it
CChristianLifeMinistryEntry *pReplacement = m_mapSwapAssignments[nID];
CString strExistingName = _T(""), strReplacementName = _T("");
GetDlgItemText(m_iSwapAssignmentSourceID, strExistingName);
CString strPrompt = _T("");
strPrompt.Format(_T("Swap assignments:\n\n%s - %s\n%s - %s\n\nPlease confirm."),
m_pEntry->GetMeetingDateAsString(),
(LPCTSTR)strExistingName,
pReplacement->GetMeetingDateAsString(),
(LPCTSTR)getter(pReplacement));
if (AfxMessageBox(strPrompt, MB_ICONQUESTION | MB_YESNO) == IDYES)
{
strReplacementName = getter(pReplacement);
setter(pReplacement, strExistingName);
if (pReplacement == m_pEntry) // Swapping assignments on same meeting!
SetDlgItemText(nReplacementCtrlID, strExistingName);
SetDlgItemText(m_iSwapAssignmentSourceID, strReplacementName);
SetModified(true);
}
}
}
模板
void CChristianLifeMinistryEditorDlg::OnSwapWith(GetterFunction&&getter,
setter函数和setter,
乌因特·奈德,
UINT重新替换Ctrlid)
{
//我们需要找到此任务的名称
自动iter=m_-mapSwapAssignments.find(nID);
if(iter!=m_mapSwapAssignments.end())
{
//我们找到了
CCHRISTIANLIFEMISTRYENTRY*PREPLACENT=m_地图通行证[nID];
CString strExistingName=\u T(“”),strReplacementName=\u T(“”);
GetDlgItemText(m_iSwapAssignmentSourceID,strExistingName);
CString struppt=\u T(“”);
strcompt.Format(\u T(“交换分配:\n\n%s-%s\n%s-%s\n\n请确认”),
m_pEntry->GetMeetingDateAsString(),
(LPCTSTR)strExistingName,
预放置->GetMeetingDateAsString(),
(LPCTSTR)吸气剂(预置换);
if(AfxMessageBox(strcompt,MB|i查询| MB|u YESNO)=idies)
{
strReplacementName=getter(预置换);
设置器(预定位,街道名称);
if(pReplacement==m_pEntry)//在同一个会议上交换任务!
SetDlgItemText(nReplacementCtrlID,StreexistingName);
SetDlgItemText(m_iSwapAssignmentSourceID,strReplacementName);
SetModified(真);
}
}
}
@IInspectable感谢您的链接。我正试图弄清楚那篇文章,但它让我的头受伤了……:)请尝试阅读以下内容:。如果你觉得它不那么伤脑筋,更接近你需要的东西,我可以帮助你进一步构建它。@badola感谢你提供了有用的答案链接。我这里的问题仍然是,这些示例都是当前类的成员函数。正如您在最后的代码中所看到的,我需要传递作为特定对象成员的函数,因为我们必须根据该对象中的成员变量获取/设置。仍然可以使用这种方法吗?通常在头文件中首选模板。虽然没有这样的限制,它必须在头文件中。我将尝试在半小时左右重构您的代码,并可能为您提供所需的答案。不要担心它会让人困惑,一开始它是对所有人的。@Andrew Truckle,如果这对你有效,那么我们可以进一步重构。请在您的代码库中使用它,并让我知道。我对你的变量知之甚少,所以没有做太多的修改。
template<typename GetterFunction, typename SetterFunction>
void CChristianLifeMinistryEditorDlg::OnSwapWith(GetterFunction && getter,
SetterFunction && setter,
UINT nID,
UINT nReplacementCtrlID)
{
// We need to locate the name for this assignment
auto iter = m_mapSwapAssignments.find(nID);
if (iter != m_mapSwapAssignments.end())
{
// We found it
CChristianLifeMinistryEntry *pReplacement = m_mapSwapAssignments[nID];
CString strExistingName = _T(""), strReplacementName = _T("");
GetDlgItemText(m_iSwapAssignmentSourceID, strExistingName);
CString strPrompt = _T("");
strPrompt.Format(_T("Swap assignments:\n\n%s - %s\n%s - %s\n\nPlease confirm."),
m_pEntry->GetMeetingDateAsString(),
(LPCTSTR)strExistingName,
pReplacement->GetMeetingDateAsString(),
(LPCTSTR)getter(pReplacement));
if (AfxMessageBox(strPrompt, MB_ICONQUESTION | MB_YESNO) == IDYES)
{
strReplacementName = getter(pReplacement);
setter(pReplacement, strExistingName);
if (pReplacement == m_pEntry) // Swapping assignments on same meeting!
SetDlgItemText(nReplacementCtrlID, strExistingName);
SetDlgItemText(m_iSwapAssignmentSourceID, strReplacementName);
SetModified(true);
}
}
}