Вам нужно использовать 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, чтобы помочь вам лучше управлять своим кодом:
Вы должны использовать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;
}