用户定义对象的重载操作符==

overloading operator== for an user-defined object

本文关键字:操作符 重载 定义 对象 用户      更新时间:2023-10-16

我有这样的代码:

struct BoughtItemData
{
    uint64 m_playerGUID;
    uint32 m_itemEntryId;
    time_t m_date;
    BoughtItemData(uint64 playerGUID, uint32 itemEntryId, time_t date) : m_playerGUID(playerGUID), m_itemEntryId(itemEntryId), m_date(date) { }
    BoughtItemData(uint64 playerGUID) : m_playerGUID(playerGUID), m_itemEntryId(0), m_date(0) { }
    bool operator==(const BoughtItemData& other) const
    {
        return m_playerGUID == other.m_playerGUID;
    }
};
typedef std::list<BoughtItemData*> ShoppingCart;

我需要在ShoppingCart上使用std::find,所以我使用这个代码:

const BoughtItemData current(player->GetGUID());
ShoppingCart::const_iterator itr = std::find(cart.begin(), cart.end(), current);
if (itr != cart.end())
//we have found something

我正在使用cart.push_back(new BoughtItemData(...))向列表中添加新项目。

错误(二进制'==':没有找到操作符,它需要类型为'const BoughtItemData'的右操作数(或没有可接受的转换))来自std::find行,我知道它没有做对,但我不确定如何做到

问题是您的列表存储指向BoughtItemData的指针,但您正在搜索BoughtItemData对象。一个解决方案是将对象存储在列表中:

typedef std::list<BoughtItemData> ShoppingCart;

您还应该仔细考虑是否需要std::list而不是std::vector


如果你真的需要存储指针(我非常怀疑你会这样做),那么你必须提供一个比较函子并将其传递给std::find_if。例如

auto cmp = [&current](const BoughtItemData* o)
           {
             return current.m_playerGUID == o->m_playerGUID;
           }
ShoppingCart::const_iterator itr = std::find_if(cart.begin(), cart.end(), cmp);

你的设计有一个根本性的缺陷。您正在存储指向对象的指针,这很好,但可以避免。然后定义名称为current的新BoughItemData,用于搜索。current的地址当然不会出现在指针列表中。

您可以考虑使用std::map并在键上搜索,例如,如果您的项目是复杂类型。

是的,您重载了相等比较操作符。这意味着像这样的代码可以工作:

BoughtItemData a,b;
bool is_equal = a == b;

然而,这不是你的编译错误所抱怨的。列表包含指针,而不是对象本身。现在,当你使用std::find对它进行迭代时,你实际上是在尝试执行这样的代码:

BoughtItemData current;
BoughtItemData* element_in_list;
bool is_equal = current == element_in_list;

你现在看到问题了吗?编译器需要一个比较操作符来比较指针和对象(让我们暂时忘记const或不const),它拥有的唯一操作符就是比较对象。

那么,你如何解决这个问题呢?您有三个主要选项:

  1. 提供一个与指针一起工作的比较操作符(这就像一个创可贴)
  2. 将列表更改为保存BoughtItemData类型的项而不是指向它的指针
  3. 使用智能指针
当你选择做什么事的时候,重要的是要知道为什么。

为什么首先要使用指针?可能是因为您不想存储重复项。你需要问自己这个列表是否是唯一存储BoughtItemData对象的地方?如果是这样,那么完全可以将对象本身存储在列表中。

如果你有几个数据结构引用同一个对象,那么你确实需要指针。但是,不要使用原始指针,使用智能指针,其中最普遍的是共享指针。共享指针将有助于消除与指针容器相关的生命周期管理的大量负担。

即使你使用了共享指针,你仍然需要提供一个自定义函数来检查底层对象的相等性,因为STL容器仍然只比较指针的值。

所以,问题的最佳解决方案取决于你设计应用程序的方式。但是我可以给你一个建议:当你有多个看起来同样好的解决方案时,总是选择最简单的。从长远来看,这将使你的代码更容易阅读、理解和维护。