Перегрузка скобки доступа и назначения C ++ - PullRequest
3 голосов
/ 24 октября 2009

Я пишу хеш-таблицу для своего класса структур данных, и я хотел бы добавить немного синтаксического сахара в мою реализацию.

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

Это прекрасно работает, когда я делаю что-то вроде cout << dict ["mykey"]. <strong>Но как я могу выполнить назначение в скобках? Что-то вроде:

dict["mykey"] = "something";

И нет, это не часть моего домашнего задания (не каламбур), я просто хочу немного лучше изучить C ++.

Ответы [ 3 ]

5 голосов
/ 24 октября 2009

Не понятно, что именно вы здесь спрашиваете. Код, который вы представили, уже поддерживает назначение. Просто сделайте это и по желанию сработает (или, по крайней мере, он должен скомпилироваться). Не имеет значения, на какой стороне оператора присваивания используется ваша перегруженная []. В левой части (LHS) он будет работать точно так же, как и в правой части (RHS) назначения (или как операнд <<, как в исходном сообщении). Ваш [] возвращает ссылку на Object, а затем фактическое назначение обрабатывается оператором присваивания вашего типа Object, что означает, что сам [] на самом деле не участвует в фактическом назначении.

Реальный вопрос здесь в том, как вы хотите, чтобы ваш [] действовал в определенных особых случаях. Что произойдет, если ваш ключ отсутствует в таблице? Ссылка на то, что Object ваш lookup собирается вернуть в этом случае?

Невозможно понять из того, что вы опубликовали. Я вижу, что он возвращает ссылку, поэтому возвращение NULL не может быть и речи. Вставляет ли новый пустой Object для данного ключа? Если так, то вам не нужно ничего делать. Ваш [] уже полностью готов к использованию на LHS задания. (Так работает [] в std::map, кстати)

В случае, если ваш lookup возвращает ссылку на специальный «охранник» Object, вы должны предпринять специальные шаги. Вы, вероятно, не хотите присваивать что-либо «охранному» объекту, поэтому вы должны как-то «отключить» его оператор присваивания, и все готово. Остальное должно работать как есть.

Если ваш lookup выдает исключение в случае несуществующего ключа, тогда вы должны решить, является ли это тем, что вы хотите, когда [] используется на LHS назначения. Если так, то вам не нужно ничего делать. Если нет, тогда потребуется дополнительная работа ...

Итак, опять же, что произойдет, если вы передадите несуществующий ключ lookup?

P.S. Кроме того, обычно имеет смысл объявить []lookup) с параметром const HashedObj& или параметром HashedObj. Неконстантная ссылка, как в вашем примере, выглядит странно и может привести к проблемам в некоторых (на самом деле, в большинстве) случаях. Я удивлен, что теперь это работает для тебя ...

3 голосов
/ 24 октября 2009

Вам нужно перегрузить это 2 раза. Тот, который будет const, который будет частью data access, и тот, который возвратит ссылку, которая будет действовать как «установщик».

2 голосов
/ 24 октября 2009

То, что вы ищете, - это функциональность, аналогичная перегруженному оператору скобок в std::map. В std::map оператор скобок выполняет поиск и возвращает ссылку на объект, связанный с конкретным ключом. Если карта не содержит какого-либо объекта, связанного с ключом, оператор вставляет новый объект в карту, используя конструктор по умолчанию.

Итак, если у вас есть std::map<K,V> mymap, то вызов mymap[someKey] либо вернет ссылку на значение, связанное с someKey, либо создаст новый объект типа V, вызвав V() ( конструктор по умолчанию V), а затем возвращает ссылку на этот новый объект, что позволяет вызывающей стороне присвоить объекту значение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...