RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 771157
Accepted
Alex Nem
Alex Nem
Asked:2020-01-16 01:34:46 +0000 UTC2020-01-16 01:34:46 +0000 UTC 2020-01-16 01:34:46 +0000 UTC

在循环遍历该向量时从向量中删除对象

  • 772

为了在 C++ 中热身,我正在 WinApi 上编写一个小型 OOP 插件,以便您可以在几行代码中创建窗口并执行必要的基本操作(例如更改文本、大小、在控件上设置事件、等等)。计划它的用途是这样的:

WqWindow::WqBegin();

WqWindow w;
WqButton b(&w);
WqTextBox tb(&w);

tb.SetPosition(WqPosition(50, 10))
    ->SetSize(WqSize(200, 25))
    ->SetText("");

b.SetText("Cool button")
    ->SetSize(WqSize(150, 25))
    ->SetPosition(WqPosition(50, 50))
    ->SetAcnhor(WqControlAnchor(false, false, true, false))
    ->SetOnClick([&b, &tb, &w]() { cout << "Clicked!" << endl; });

w.SetTitle("Cool window")
    ->SetSize(WqSize(400, 400))
    ->ClosesProgram(false)
    ->SetOnClose([]() { cout << "Closed!" << endl; return true; })
    ->Show();

WqWindow::WqEnd();

原理是这样的——创建控件时,将指向它的指针添加到窗口对象(WqWindow)的元素向量中,删除时,在析构函数中,从向量中删除该元素。大致是这样的

//Убираем из списка элементов управления окна
this->window_->controls_.erase(std::remove(this->window_->controls_.begin(), this->window_->controls_.end(), this), this->window_->controls_.end());

按钮和其他元素本身的事件在窗口过程中处理。原理大致如下:我们获取导致事件的窗口句柄(HWND),使用自定义指针(在创建 WqWindow 窗口时分配),我们获取关联的 WqWindow 对象并访问控制向量。我们循环遍历它们,并调用这些元素的 lambda 函数。它看起来像这样:

    case WM_COMMAND:
        if (wqWindow && !wqWindow->controls_.empty()) {
            const std::vector<WqControl*> safeControlPointers(wqWindow->controls_);

            for (WqControl * control : safeControlPointers) 
            {
                if (control->initialized_)
                {
                    if (HIWORD(wParam) == EN_CHANGE) {
                        if (control && control->ControlClassName() == "Edit" && control->GetHWND() == (HWND)(lParam)) {
                            WqTextBox * pTextBox = ((WqTextBox*)control);
                            if (pTextBox->onChanged_) {
                                pTextBox->onChanged_();
                            }
                        }
                    }
                    else {
                        if (control->ControlClassName() == "Button" && control->GetHWND() == (HWND)(lParam)) {
                            WqButton * pButton = ((WqButton*)control);
                            if (pButton->onClick_) {
                                pButton->onClick_();
                            }
                        }
                    }
                }
            }
        }
        break;

然后我想 - 如果这个库的用户想要删除(通过调用析构函数)lamb 表达式中的一些控件,例如像这样:

->SetOnClick([&b, &tb, &w]() { tb.~WqTextBox(); });

在这种情况下,我只是添加了 safeControlPointers 变量,这样当通过向量时,我们就像使用向量的副本一样工作,而不是使用大小会改变的向量。似乎一切都应该井井有条,但在执行过程中(按下按钮时)仍然发生错误。事实是,在向量的副本中有一个指向某个对象的指针,该对象以某种方式被删除了。我不知道怎么做,但以下内容帮助了我——我在 WqControl 中声明了 control->initialized_ 标志,它在构造函数中变为真,并在析构函数中设置为flase。在循环中,您可能注意到了检查

if (control->initialized_)

正是由于这一点,按下按钮时程序没有中断。我不完全明白为什么(毕竟,对象被破坏,从内存中删除,所以访问它的任何成员是不可能的)。如果你能解释这是怎么可能的,我会很高兴。好吧,我并没有就此止步,而是决定尝试创建一个 TextBox(我后来决定单击时删除),而不是在堆栈上,而是在堆上(即使用 new 运算符),然后调用 delete on点击。这就是一切最终崩溃的地方。并且没有检查帮助(指针空虚和其他)。

问题:如何实现类似的机制,以便在单击时可以删除其他元素?解决这个问题的正确方法是什么?提前致谢。

c++
  • 1 1 个回答
  • 10 Views

1 个回答

  • Voted
  1. Best Answer
    Alex Nem
    2020-01-16T04:45:15Z2020-01-16T04:45:15Z

    谢谢大家的建议,看来问题已经解决了。我刚刚摆脱了处理 WM_COMMAND 消息的循环。每个控件都有一个自定义对象指针(它包含所有必要的回调函数)。由于某种原因,我忘记了它。我只是获取控件的句柄,然后从中获取此指针,并调用必要的函数。现在看起来像这样:

        case WM_COMMAND:
            if (lParam) {
                WqControl * wqControl = (WqControl*)GetWindowLongPtr((HWND)(lParam), GWLP_USERDATA);
    
                if (wqControl) {
                    if(wqControl->ControlClassName() == "Edit"){
                        WqTextBox * pTextBox = ((WqTextBox*)wqControl);
                        if (pTextBox->onChanged_) {
                            pTextBox->onChanged_();
                        }
                    }
                    else if (wqControl->ControlClassName() == "Button") {
                        WqButton * pButton = ((WqButton*)wqControl);
                        if (pButton->onClick_) {
                            pButton->onClick_();
                        }
                    }
                }
            }
            break;
    

    结果,循环不会开始,从向量中删除时也不会发生错误。事实上,事实证明,没有必要存储指针列表。至少目前看来是这样。

    • 0

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    是否可以在 C++ 中继承类 <---> 结构?

    • 2 个回答
  • Marko Smith

    这种神经网络架构适合文本分类吗?

    • 1 个回答
  • Marko Smith

    为什么分配的工作方式不同?

    • 3 个回答
  • Marko Smith

    控制台中的光标坐标

    • 1 个回答
  • Marko Smith

    如何在 C++ 中删除类的实例?

    • 4 个回答
  • Marko Smith

    点是否属于线段的问题

    • 2 个回答
  • Marko Smith

    json结构错误

    • 1 个回答
  • Marko Smith

    ServiceWorker 中的“获取”事件

    • 1 个回答
  • Marko Smith

    c ++控制台应用程序exe文件[重复]

    • 1 个回答
  • Marko Smith

    按多列从sql表中选择

    • 1 个回答
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Suvitruf - Andrei Apanasik 什么是空? 2020-08-21 01:48:09 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5