从触摸回调访问矢量元素的方法时,BAD ACCESS错误

时间:2019-05-09 06:38:29

标签: c++ cocos2d-x cocos2d-x-3.0

我的类结构如下:

class A
{
 public:
     virtual void func() = 0;
};

class B : public A
{
 public:
     virtual void func();
};

我在相应的.cpp文件中提供了B的func的实现。

void B::func()
{
     cocos2d::log("Hello");
}

现在,当我尝试从另一个文件访问B的函数时,如下所示:

class XYZ
{
 public:
    public void func2();
 protected:
    cocos2d::EventListenerTouchOneByOne * _Listener = nullptr;
    std::vector<A *> _List;

    bool touchBeginCallback(cocos2d::Touch *touch, cocos2d::Event *event);
    void touchEndCallback(cocos2d::Touch *touch, cocos2d::Event *event);
};

在XYZ.cpp中

void XYZ::func2()
{
    _List.push_back(new B());
    _List.push_back(new B());
    _List.push_back(new B());
    _List.push_back(new B());
    _List.push_back(new B());

    for(auto itr = _List.begin(); itr != _List.end(); itr++)
    {
        A * a = (*itr);
        if(a)
        {
            a->func(); // Here it works fine
        }
    }

    _Listener = cocos2d::EventListenerTouchOneByOne::create();
    _Listener->setSwallowTouches(true);
    _Listener->onTouchBegan = (cocos2d::EventListenerTouchOneByOne::ccTouchBeganCallback) CC_CALLBACK_2(XYZ::touchBeginCallback, this);
    _Listener->onTouchEnded = (cocos2d::EventListenerTouchOneByOne::ccTouchCallback) CC_CALLBACK_2(XYZ::touchEndCallback, this);

    cocos2d::Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(_Listener, this);
}

bool XYZ::touchBeginCallback(cocos2d::Touch *touch, cocos2d::Event *event)
{
    return true;
}

void XYZ::touchEndCallback(cocos2d::Touch *touch, cocos2d::Event *event)
{
    for(auto itr = _List.begin(); itr != _List.end(); itr++)
    {
        A *a = (*itr);
        if(a)
        {
            a->func(); // Throws bad access error
        }
    }
}

如果我从XYZ中的方法调用func()调用(或更确切地说,访问类型B的对象),效果很好,但是如果我从touchEndCallback方法调用它,则崩溃并出现BAD_ACCESS错误。

当我在func2()中以调试模式检查_List时,它正确显示_List具有五个 B型成员,但是当我检查了列表在touchEndCallback方法中,它表明_List具有五个类型A 的成员。

为什么会发生崩溃,该如何解决?

1 个答案:

答案 0 :(得分:2)

取消引用迭代器以获取指针A *。 循环应如下所示:

for(auto itr = _List.begin(); itr != _List.end(); itr++)
{
    if (*itr)
        (*itr)->func();
}

或者您可以将范围用于:

  for(auto pa : _List)  // now you're gettting A* 's directly
    {
        if (pa)
           pa->func();    
    }

编辑:使用原始指针也是一个坏主意。考虑 unique_ptr shared_ptr 。 如果仍然有错误,则可能是您正在其他地方删除对象,因此列表包含无效的指针。但是,如果没有完整的代码,很难说是怎么回事。如果要在其他地方删除对象,则需要将List的A *显式设置为nullptr,否则,如果(a)仍为true。