std :: find返回一个我无法访问函数的类

时间:2018-12-03 19:53:45

标签: c++ vector

我来自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没有为我显示任何内容。结果存在。

如何访问该功能?还有另一种更好的方法吗?

2 个答案:

答案 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();

这应该提供相同的组装,两种可能。