从触摸回调访问矢量元素的方法时出现 BAD ACCESS 错误
BAD ACCESS error when accessing method of vector element from touch callback
我有一个class结构如下:
class A
{
public:
virtual void func() = 0;
};
class B : public A
{
public:
virtual void func();
};
和我在相应的.cpp文件中提供了B的函数的实现。
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 有五个成员 type A.
为什么会发生此崩溃,我该如何解决?
取消引用迭代器以获取指针 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 包含无效指针。但是没有完整的代码很难说发生了什么。如果对象在其他地方被删除,那么您需要明确地将 List 的 A* 设置为 nullptr,否则 if (a) 仍会计算为 true。
我有一个class结构如下:
class A
{
public:
virtual void func() = 0;
};
class B : public A
{
public:
virtual void func();
};
和我在相应的.cpp文件中提供了B的函数的实现。
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 有五个成员 type A.
为什么会发生此崩溃,我该如何解决?
取消引用迭代器以获取指针 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 包含无效指针。但是没有完整的代码很难说发生了什么。如果对象在其他地方被删除,那么您需要明确地将 List 的 A* 设置为 nullptr,否则 if (a) 仍会计算为 true。