我来自C / C#语言,现在我试图学习C ++及其标准功能。
现在,我正在创建一个名为IMonsterDead
的类。我将有一个std::vector<IMonsterDead*>
的怪物,N
。
示例:
class IMonsterDead {
public:
IMonsterDead(int Id)
{
this->_Id = Id;
}
virtual void OnDead() = 0;
int Id() const {
return _Id;
}
private:
int _Id;
};
实现该类的一个类:
class MonsterTest : public IMonsterDead {
public:
MonsterTest(int generId)
: IMonsterDead(generId)
{
}
virtual void OnDead()
{
std::cout << "MonsterTesd died" << std::endl;
}
};
好的,如果我直接访问,一切正常。但是我正在尝试使用std::find
。
完整程序测试:
int main()
{
std::vector<IMonsterDead*> monsters;
for (int i = 0; i < 1000; i++)
{
monsters.emplace_back(new MonsterTest(1000 + i));
}
int id = 1033;
std::vector<IMonsterDead*>::iterator result = std::find(monsters.begin(), monsters.end(), [id]( IMonsterDead const* l) {
return l->Id() == id;
});
if (result == monsters.end())
std::cout << "Not found" << std::endl;
else
{
// Here I want to access OnDead function from result
}
return 0;
}
所以我需要从OnDead
访问result
函数,但不能。 Intellisense没有为我显示任何内容。结果存在。
如何访问该功能?还有另一种更好的方法吗?
答案 0 :(得分:6)
您需要使用std::find_if()
而不是std::find()
。 std::find()
用于查找具有特定值的元素,因此您必须将其实际值传递给它,而不是user_defined谓词。 std::find_if()
用于基于谓词查找元素。
无论哪种方式,如果找到匹配项,则对返回的迭代器进行解引用将为您提供IMonsterDead*
指针(更准确地说,它将为您提供IMonsterDead*&
引用指针)。然后,您需要取消引用该指针才能访问任何成员,例如OnDead()
。
您还正在泄漏内存。您不是delete
正在new
的对象。而且,当处理通过指向基类的指针删除的多态类型时,基类需要一个virtual
析构函数,以确保正确调用所有派生的析构函数。
话虽如此,您显然正在使用C ++ 11或更高版本(实际上,您正在使用vector::emplace_back()
),因此您应该使用C ++ 11功能来帮助您更好地管理代码: / p>
您应该使用std::unique_ptr
包裹怪物对象,这样就无需手动delete
。
在覆盖虚拟方法时,应始终使用override
关键字,以确保正确覆盖它。使用override
时,编译器会比不使用时捕获更多的语法错误。
每当声明一个编译器可以为您推断其类型的变量时,都应使用auto
。在处理模板代码时特别有用。
尝试更多类似的方法:
#include <iostream>
#include <vector>
#include <memory>
#include <algorithm>
class IMonsterDead {
public:
IMonsterDead(int Id)
: m_Id(Id)
{
}
virtual ~IMonsterDead() {}
virtual void OnDead() = 0;
int Id() const {
return m_Id;
}
private:
int m_Id;
};
class MonsterTest : public IMonsterDead {
public:
MonsterTest(int generId)
: IMonsterDead(generId)
{
}
void OnDead() override
{
std::cout << "MonsterTest died" << std::endl;
}
};
int main()
{
std::vector<std::unique_ptr<IMonsterDead>> monsters;
for (int i = 0; i < 1000; i++)
{
// using emplace_back() with a raw pointer risks leaking memory
// if the emplacement fails, so push a fully-constructed
// std::unique_ptr instead, to maintain ownership at all times...
monsters.push_back(std::unique_ptr<IMonsterDead>(new MonsterTest(1000 + i)));
// or:
// std::unique_ptr<IMonsterDead> monster(new MonsterTest(1000 + i));
// monsters.push_back(std::move(monster));
// or, if you are using C++14 or later:
// monsters.push_back(std::make_unique<MonsterTest>(1000 + i));
}
int id = 1033;
auto result = std::find_if(monsters.begin(), monsters.end(),
[id](decltype(monsters)::value_type &l) // or: (decltype(*monsters.begin()) l)
{
return (l->Id() == id);
}
// or, if you are using C++14 or later:
// [id](auto &l) { return (l->Id() == id); }
);
if (result == monsters.end())
std::cout << "Not found" << std::endl;
else
{
auto &monster = *result; // monster is 'std::unique_ptr<IMonsterDead>&'
monster->OnDead();
}
return 0;
}
答案 1 :(得分:2)
迭代器是一个有趣的抽象,在这种情况下,简化为指针。
要么收到指向元素的指针,要么得到无效的结尾。
您可以将其用作指针:(*result)->func();
您也可以使用它来创建新变量:
IMonsterDead &m = **result;
m.func();
这应该提供相同的组装,两种可能。