【问题标题】:Overload bracket access and assignment C++重载括号访问和赋值 C++
【发布时间】:2009-10-24 17:05:13
【问题描述】:

我正在为我的数据结构类编写一个哈希表,我想在我的实现中添加一点语法糖。

template <typename HashedObj, typename Object>
Object & Dictionary<HashedObj, Object>::operator[](HashedObj & key)
{
  return items.lookup(key);
}

当我执行 cout 但是我怎样才能用括号做赋值呢? 像:

dict["mykey"] = "something";

不,这不是我家庭作业的一部分(不是双关语),我只是想更好地学习 C++。

【问题讨论】:

  • 顺便说一句,当您声明 Dictionary 用于字符串键时,您使用哪种类型作为 HashedObj?就像上面示例中的"mykey"
  • 因为您正在返回一个引用,所以赋值运算符应该按照您期望的方式工作。唯一的问题是lookup() 找不到键,那你怎么办?
  • 在我的测试中,我使用字符串: Dictionary dict;
  • @Matt:在这种情况下,您的代码不应该编译。当您执行 dict["mykey"] 时,编译器会创建一个临时的 string 对象。临时对象不能传递给operator[],因为后者接受非常量引用作为参数。非常量引用不能绑定到临时。如果它编译,那只是因为你的编译器允许它作为扩展(我猜是 MSVC++)。同样,您的 operator[](和 lookup 函数)应使用 const HashedObj&amp; 参数声明。
  • 我不清楚,我实际上并没有运行 dict["mykey"] 我运行 string key = "mykey"; dict[key] = "something"。我认为他们会做同样的事情,所以我在我的问题中简化了它。显然,我不知道我在做什么 :) 我尝试了 dict["mykey"] 并且它无法编译。现在我知道为什么了。谢谢。现在事情开始变得有意义了。

标签: c++ operator-overloading


【解决方案1】:

目前尚不清楚您在这里问的是什么。您提供的代码已经支持赋值。只需这样做,就可以随意工作(或者至少它应该编译)。在赋值运算符的哪一侧使用重载的[] 绝对没有区别。它在左侧 (LHS) 上的工作方式与在赋值的右侧 (RHS) 上的工作方式完全相同(或作为 &lt;&lt; 的操作数,如您的原始帖子中所示)。你的[] 返回一个Object 的引用,然后实际的赋值由你的Object 类型的赋值运算符处理,这意味着[] 本身并没有真正参与实际的赋值。

这里真正的问题是您希望您的[] 在某些特殊情况下如何操作。如果您的密钥不在表中,会发生什么?参考Object 在这种情况下您的lookup 将返回什么?

不可能从您发布的内容中弄清楚。我看到它返回一个引用,所以返回 NULL 是没有问题的。它是否为给定的键插入一个新的空Object?如果是这样,那么您无需执行任何操作。您的[] 已经完全准备好在作业的 LHS 上使用。 (这就是std::map 中的[] 的工作原理,顺便说一句)

如果您的 lookup 返回对特殊“守卫”Object 的引用,您必须采取特殊步骤。您可能不想将任何东西分配给“守卫”对象,因此您必须以某种方式“禁用”其分配运算符,然后您就完成了。其余的应该按原样工作。

如果您的lookup 在密钥不存在的情况下抛出异常,那么当[] 用于分配的LHS 时,您必须确定这是否是您想要的。如果是这样,那么你不需要做任何事情。如果没有,那将需要一些额外的工作......

同样,如果您将不存在的密钥传递给lookup,会发生什么?

附:此外,使用const HashedObj&amp; 参数或仅使用HashedObj 参数来声明[](和lookup)通常更有意义。如您的示例所示,非常量引用看起来很奇怪,并且在某些(实际上,在大多数情况下)可能会导致问题。我很惊讶它现在对你有用...

【讨论】:

  • 我猜它已经支持赋值了。我想这会比这更难!我不太担心这个简单程序的特殊情况,但感谢您指出。
  • 我支持通过=操作符赋值。
  • @Matt:为了 100% 清楚,operator[] 返回一个 Object 引用。必须支持分配的是Object 类。 Dictionary 类也可能支持赋值,但这里没有使用。
  • @D.Shawley:我刚刚在回复中添加了相同的内容,与您同时进行。
【解决方案2】:

您需要超载 2 次。一个是const,它将是data access 部分,一个将返回一个引用,它将充当“setter”。

【讨论】:

    【解决方案3】:

    您正在寻找的是类似于std::map 中的重载括号运算符的功能。在std::map 中,括号运算符执行查找并返回对与特定键关联的对象的引用。如果映射不包含任何与该键关联的对象,则运算符使用默认构造函数将新对象插入映射中。

    所以,如果您有std::map&lt;K,V&gt; mymap,那么调用mymap[someKey] 将返回对与someKey 关联的值的引用,否则它将通过调用V() 创建一个V 类型的新对象( V) 的默认构造函数,然后返回对该新对象的引用,这允许调用者为该对象赋值。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多