2016-08-08 3 views
1

Обновление:
This was a bug in wxWidgets. Это было исправлено в wxWidgets 3.1.1, если вы используете компилятор, совместимый с C++ 11.Преобразование в производном классе недоступно, если базовый класс защищен

Я пытаюсь динамически привязывать обработчик события к событию в wxWidgets. К сожалению, если производный класс защищен, он, похоже, не работает.

Минимальный пример:

// Test.h 
class Test : protected wxFrame 
{ 
public: 
    Test(); 

private: 
    void sizing(wxSizeEvent& event); 
}; 

// Test.cpp 
Test::Test() 
{ 
    Bind(wxEVT_SIZING, &Test::sizing, this); 
} 

void Test::sizing(wxSizeEvent& event) 
{ 
} 

Это, к сожалению, не похоже на работу и сетей следующее сообщение об ошибке на Visual Studio 2015 Update 3:

wxWidgets\include\wx/meta/convertible.h(31): error C2243: 'type cast': conversion from 'Test *' to 'wxEvtHandler *' exists, but is inaccessible 
    wxWidgets\include\wx/event.h(335): note: see reference to class template instantiation 'wxConvertibleTo<Class,wxEvtHandler>' being compiled 
      with 
      [ 
       Class=Test 
      ] 
    wxWidgets\include\wx/event.h(3568): note: see reference to class template instantiation 'wxEventFunctorMethod<EventTag,Test,EventArg,EventHandler>' being compiled 
      with 
      [ 
       EventTag=wxEventTypeTag<wxSizeEvent>, 
       EventArg=wxSizeEvent, 
       EventHandler=Test 
      ] 
    Test.cpp(78): note: see reference to function template instantiation 'void wxEvtHandler::Bind<wxEventTypeTag<wxSizeEvent>,Test,wxSizeEvent,Test>(const EventTag &,void (__cdecl Test::*)(EventArg &),EventHandler *,int,int,wxObject *)' being compiled 
      with 
      [ 
       EventTag=wxEventTypeTag<wxSizeEvent>, 
       EventArg=wxSizeEvent, 
       EventHandler=Test 
      ] 

Изменение наследования для общественности делает его работу:

class Test : public wxFrame 
  1. Почему преобразование недоступно, когда наследование защищено?
  2. Я не хочу раскрывать wxFrame миру, а только классы, которые производят класс Test. Как я могу это сделать, все еще имея возможность динамически связывать обработчик событий?
+2

Что такое 'Bind()'? – Barry

+1

Почему вы ожидаете, что защищенное наследование будет работать на вас? Это не так. Структуры OO в C++ полагаются на публичное наследование. –

+1

@Barry Bind - метод, который привязывает данный метод к вызову всякий раз, когда выполняется данное событие (в данном случае SIZING). Дополнительную информацию см. В http://docs.wxwidgets.org/trunk/overview_events.html#overview_events_bind. – tambre

ответ

1

Вы можете обойти это с помощью следующего:

Bind(wxEVT_SIZING, std::bind(&Test::sizing, this, std::placeholders::_1)); 

Минимального образца, который компилирует:

#include <wx/wx.h> 
#include <functional> 
using namespace std::placeholders; 

class Test : protected wxFrame 
{ 
public: 
    Test(); 

private: 
    void sizing(wxSizeEvent& event); 
}; 
Test::Test() 
{ 
    Bind(wxEVT_SIZING, std::bind(&Test::sizing, this, _1)); 
} 

void Test::sizing(wxSizeEvent& event) 
{ 
} 

class MyApp: public wxApp 
{ 
public: 
    virtual bool OnInit(); 
}; 
class MyFrame: public wxFrame 
{ 
public: 
    MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size); 
private: 
}; 
wxIMPLEMENT_APP(MyApp); 
bool MyApp::OnInit() 
{ 
    MyFrame *frame = new MyFrame("", wxPoint(50, 50), wxSize(450, 340)); 
    frame->Show(true); 
    return true; 
} 

MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size) : wxFrame(NULL, wxID_ANY, title, pos, size) 
{ 
    Test* test = new Test(); 
} 
1

Это действительно выглядит как дефект WxWidgets обработки событий кода, потому что ошибка происходит из проверка сделана wxConvertibleTo, чтобы определить, получается ли Test от wxEvtHandler или нет (и здесь он не публикуется).

Простейшим решением, которое я могу порекомендовать, является использование временной лямбды, которая обходит эту проверку, например. это работает (при условии, что вы, конечно, используете C++ 11):

#include <wx/frame.h> 

class Test : protected wxFrame { 
public: 
    Test() { Bind(wxEVT_SIZING, [=](wxSizeEvent& e) { sizing(e); }); } 

private: 
    void sizing(wxSizeEvent&) { } 
}; 
Смежные вопросы