существует ли лучший способ выбрать корректную перегрузку метода?

Это действительно единственный способ получить корректный адрес для функции экземпляра:

typedef CBitmap * (CDC::* SelectObjectBitmap)(CBitmap*);
SelectObjectBitmap pmf = (SelectObjectBitmap)&CDC::SelectObject;

Во-первых, нужно создать определение типа, и затем нужно использовать это, чтобы вынудить компилятор выбрать корректный перегруженный метод при взятии его адреса?

Нет ли никакой синтаксис, который является более естественным, и автономным, таким как:

SelecdtObjectBitmap pmf = &CDC::SelectObject(CBitmap*);

Я часто использую ScopeGuard в моем коде. И одно очевидное использование должно гарантировать, что любые временные объекты CDC сначала выбраны в данный DC, затем удалили в выходе объема, заставив мой код протечь свободный даже при исключительных обстоятельствах - и одновременно очистив записанный код (глупый несколько путей выхода и попытки/выгоды и так далее, чтобы попытаться обработать удаление любых выбранных объектов от данного CDC).

Таким образом, более полный пример того, что я в настоящее время вынуждаюсь сделать, похож:

// get our client rect
CRect rcClient;
GetClientRect(rcClient);

// get the real DC we're drawing on
PAINTSTRUCT ps;
CDC * pDrawContext = BeginPaint(&ps);

// create a drawing buffer
CBitmap canvas;
canvas.CreateCompatibleBitmap(pDrawContext, rcClient.Width(), rcClient.Height());

CDC memdc;
memdc.CreateCompatibleDC(pDrawContext);

//*** HERE'S THE LINE THAT REALLY USES THE TYPEDEF WHICH i WISH TO ELIMINATE ***//
ScopeGuard guard_canvas = MakeObjGuard(memdc, (SelectObjectBitmap)&CDC::SelectObject, memdc.SelectObject(&canvas));

// copy the image to screen
pDrawContext->BitBlt(rcClient.left, rcClient.top, rcClient.Width(), rcClient.Height(), &memdc, rcClient.left, rcClient.top, SRCCOPY);

// display updated
EndPaint(&ps);

Это всегда казалось мне глупо адом, что мне нужна к определению типа каждая перегруженная функция, из которой я хочу взять адрес.

Так... существует ли лучший путь?!

Править: На основе ответов люди предоставили, я полагаю, что у меня есть решение моей базовой потребности: т.е. иметь более естественный синтаксис для MakeGuard, который выводит корректное переопределение SelectObject для меня:

template 
ObjScopeGuardImpl1 MakeSelectObjectGuard(CDC & dc, GDIObj * pGDIObj)
{
    return ObjScopeGuardImpl1::MakeObjGuard(dc, (GDIObj*(CDC::*)(GDIObj*))&CDC::SelectObject, dc.SelectObject(pGDIObj));
}

Который заставляет мой выше кода измениться на:

ScopeGuard guard_canvas = MakeSelectObjectGuard(memdc, &canvas);

//////////////////////////////////////////////////////////

Для тех, кто мог бы здесь искать версию не-MFC того же самого:

//////////////////////////////////////////////////////////////////////////
//
// AutoSelectGDIObject
//  selects a given HGDIOBJ into a given HDC,
//  and automatically reverses the operation at scope exit
//
// AKA:
//  "Tired of tripping over the same stupid code year after year"
//
// Example 1:
//  CFont f;
//  f.CreateIndirect(&lf);
//  AutoSelectGDIObject select_font(*pDC, f);
//
// Example 2:
//  HFONT hf = ::CreateFontIndirect(&lf);
//  AutoSelectGDIObject select_font(hdc, hf);
//
// NOTE:
//  Do NOT use this with an HREGION.  Those don't need to be swapped with what's in the DC.
//////////////////////////////////////////////////////////////////////////

class AutoSelectGDIObject
{
public:
    AutoSelectGDIObject(HDC hdc, HGDIOBJ gdiobj) 
        : m_hdc(hdc)
        , m_gdiobj(gdiobj)
        , m_oldobj(::SelectObject(m_hdc, gdiobj))
    {
        ASSERT(m_oldobj != m_gdiobj);
    }

    ~AutoSelectGDIObject()
    {
        VERIFY(m_gdiobj == ::SelectObject(m_hdc, m_oldobj));
    }

private:
    const HDC       m_hdc;
    const HGDIOBJ   m_gdiobj;
    const HGDIOBJ   m_oldobj;
};

//////////////////////////////////////////////////////////

Спасибо Все, кто ответил и прокомментировал!:D

5
задан Mordachai 14 January 2010 в 17:22
поделиться