【问题标题】:Conversion in derived class inaccessible if base class is protected如果基类受保护,则派生类中的转换不可访问
【发布时间】:2016-08-08 15:26:51
【问题描述】:

更新:
This was a bug in wxWidgets。如果您使用的是与 C++11 兼容的编译器,此问题已在 wxWidgets 3.1.1 中得到修复。


我正在尝试将事件处理程序动态绑定到 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 类的类。如何在仍然能够动态绑定事件处理程序的同时做到这一点?

【问题讨论】:

  • 您为什么希望受保护的继承对您有用?它不会。 C++ 中的 OO 框架依赖于公共继承。
  • @Barry Bind 是一种绑定给定方法的方法,只要给定事件(在本例中为 SIZING)被执行,就会被调用。请参阅docs.wxwidgets.org/trunk/… 了解更多信息。
  • @n.m.我不确定你的意思,但我看不出为什么将继承更改为受保护会导致转换变得不可访问。
  • 你可以加好友Bind,这样可以解决问题
  • 错误信息应该包含行号和可能发生故障的函数。那是什么功能?

标签: c++ inheritance c++14 wxwidgets


【解决方案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();
}

【讨论】:

    【解决方案2】:

    这确实看起来像 wxWidgets 事件处理代码中的缺陷,因为错误来自 wxConvertibleTo 所做的检查,以确定 Test 是否派生自 wxEvtHandler(这里它不公开) .

    我可以推荐的最简单的修复方法是使用临时 lambda,它绕过了这个检查,例如这行得通(当然,前提是你使用 C++11):

    #include <wx/frame.h>
    
    class Test : protected wxFrame {
    public:
        Test() { Bind(wxEVT_SIZING, [=](wxSizeEvent& e) { sizing(e); }); }
    
    private:
        void sizing(wxSizeEvent&) { }
    };
    

    【讨论】:

      猜你喜欢
      • 2016-03-11
      • 2014-08-27
      • 2011-06-08
      • 2012-01-23
      • 2019-01-20
      • 1970-01-01
      • 2012-08-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多