尽量避免继承 wxSocketBase 类和它的子类来接收事件

这是wxWidgets论坛的中文版本。在这里,您可以用您的母语汉语讨论上面任一子论坛所涉及的所有关于wxWidgets的话题。欢迎大家参与到对有价值的帖子的中英互译工作中来!
Post Reply
ChunJiu
Knows some wx things
Knows some wx things
Posts: 35
Joined: Thu Jun 05, 2014 2:52 pm

尽量避免继承 wxSocketBase 类和它的子类来接收事件

Post by ChunJiu » Sat Jul 12, 2014 1:11 pm

学习日志 2014.7.12

因事先不知道 wxSockteBase 的工作原理,从它的继承类 wxSocketClient 创建了一个自己的类,打算将 scoket 简化一下使用,结果遇到了很奇怪的事情,纠结了很久很久才发现吃了一个大亏。

我的 Socket_Client 类是这样定义的:

Code: Select all

    class Socket_Client : public wxSocketClient, public wxEvtHandler 
    { 
        ... 
        void OnSocketEvent(wxSocketEvent&);
    } ;
它继承了wxSocketClient 类和 wxEvtHandler 类,并在类中定义了 socket 事件的处理函数:
void OnSocketEvent(wxSocketEvent&);

原来是打算创建一个 socket client 对象,并在实现 socket 连接(Connect)后可自己接收 socket 事件,如此做一个模板能简化后续的工作。但在实际调试中总是产生异常导致运行中断失败,类中定义的所有变量成员全部失效,原来预置的值也全部变成了随机数。

开始以为是哪个随机指针越界产生的写错误,但一直也没有跟踪到什么指针出错,就一直纠结啊?为什么一响应事件,所有的变量位置都变了... 突然灵光一闪,仔细检查才发现响应 socket 事件的对象不是之前的对象实例...... 花了两天时间,疯狂吐血!

原来, wxSocketBase 类在响应事件时,为这个事件又创建了一个新的 Socket_Client 类对象的实例,然后在新创建的对象实例中响应此事件。然而这个新对象实例的所有成员变量都没有赋过值,当然全是随机数......

第一种解决方法:

随后立即改代码,将原来对 wxSocketClient 的继承取消,改成在类中用 new 生成一个 wxSocketClient 对象,只响应这个对象实例的 socket 事件。之后这个新定义的类就一切工作都正常了,再怎么中断都不会出错。跟踪的所有成员变量都保持了正确的赋值。

第二种解决方法:

在研究这个问题的过程中找到了之前的对象实例的正确位置,前面那种问题其实也有解决方案。即用 wxSocketEvent 事件类的对象成员函数 GetSocket() 来获取之前那个正确对象实例的指针。只要用该指针就能使前面那个类定义的代码正确运行。下面就是在事件的响应函数中加一个类的对象指针,给它赋值,然后通过这个指针来访问正确对象实例的成员。

但这种做法有个后患,它依赖于当前的 wxWidgets 库定义的工作模式,倘若哪天库的工作模式修改了,这样的做法就失效了,所以还是第一种解决方法更可靠。

Code: Select all

void Socket_Client :: OnSocketEvent ( wxSocketEvent & e )
{
    Socket_Client * obj = (Socket_Client *)(e.GetSocket());

    switch(e.GetSocketEvent())
    {
    case wxSOCKET_CONNECTION:
        obj->OnConnect();
        break;

    case wxSOCKET_INPUT:
        obj->OnInput();
        break;

    case wxSOCKET_OUTPUT:
        obj->OnOutput();
        break;

    case wxSOCKET_LOST:
        obj->OnLost();
        break;
    } 
} 

Post Reply