Перегрузка присваивания скобок в C++

Я занимаюсь переносом приложения Objective-C на C++ и решил создать класс, аналогичный NSObject и NSDictionary. Если вы не знакомы с этой системой, NSObject — это объект, который все объекты наследуют в Obj-C, а затем в нем есть механизм подсчета ссылок. Когда ссылок больше нет, объект освобождается.

В моем коде я хотел бы иметь возможность сделать следующее

CMDictionary["Key"] = Object;

Внутренне это хранится как

Map<string, CMObject*> mDictionary

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

CMDicionary["key"]->StringValue();

Будет ли в любом случае это делать, или мне нужно будет просто использовать функции getter/setter для изменения моего словаря


person David    schedule 14.07.2012    source источник
comment
Не переусердствуйте и не подходите к этому с таким строгим мышлением ООП — замените NSObject на std::shared_ptr<> и NSDictionary на std::unordered_map<>. То, как вы пытаетесь это сделать, было бы в лучшем случае неудобным правильно отслеживать CMObject*, которые вы должны выделить и выделить (как вы, кажется, обнаруживаете, очевидно из ваших ответов на текущие ответы).   -  person ildjarn    schedule 14.07.2012
comment
Я переношу на кросс-платформенную систему, которая распространяется на различные архитектуры (мобильные и настольные). Стандарты C++ 11 пока недоступны и не будут доступны в течение некоторого времени.   -  person David    schedule 14.07.2012
comment
Не уверен, о чем вы думаете, но стандарт C++11 был опубликован с 11 апреля 2011 года... Добро пожаловать в 2012 год? ;-]   -  person ildjarn    schedule 14.07.2012
comment
Они пока недоступны для одновременной кросс-компиляции на Symbian, iOS, Android, Bada, ПК и OSX с использованием платформы Marmalade. Надеюсь, это прояснит ситуацию.   -  person David    schedule 14.07.2012


Ответы (3)


Что вы обычно делаете в этой ситуации, так это реализуете:

Object const& Map::operator[](string) const;
Object& Map::operator[](string);

Обратите внимание, что я написал Object& вместо Object. В любом случае вы можете создать экземпляр нового объекта и передать его, полагаясь на надлежащую реализацию Object& Object::operator=(Object const&), которая затем выполнит назначение после возврата вашей Map::operator[] функции (не волнуйтесь, компилятор оптимизирует его в большинстве случаев).

person bitmask    schedule 14.07.2012
comment
Звучит здорово! Я не понимал, что это было законно в С++. Я проверю это и отмечу, что это был ответ, если он работает правильно. - person David; 14.07.2012
comment
Я только что подумал о проблеме... Я могу сказать по тому, что передается, если мне нужно будет освободить старый объект, но я не вижу способа сохранить какой-либо новый объект, который назначается с помощью этого метода. - person David; 14.07.2012
comment
@David: Боюсь, я не понимаю, что ты имеешь в виду. Не могли бы вы уточнить? - person bitmask; 14.07.2012
comment
Поэтому, когда я присваиваю, я бы использовал этот псевдокод: SetObject(key k, object o) {if(isSet(k) Objects[k]->release; InternalDictSet(k,o);o->retain;} При использовании скобки, я бы знал, что мой объект будет перезаписан с помощью Object& Map::operator[](string); поэтому я мог бы освободить старый объект, если бы он был там для этого ключа, но не было бы возможности сохранить новый объект, который я вижу. - person David; 14.07.2012
comment
Я думаю, что это то, что принадлежит классу Object. Ваша карта должна заниматься только размещением первого объекта в этом слоте, а затем возвращать только ссылку на него. - person bitmask; 14.07.2012

Вы должны перегрузить operator[], чтобы принять строку.

http://courses.cms.caltech.edu/cs11/material/cpp/donnie/cpp-ops.html

person retrohacker    schedule 14.07.2012
comment
Это не решает всей проблемы. Читай внизу моего поста. Как узнать, используете ли вы его для назначения или для чтения? Вы же не хотите дважды сохранить только потому, что вы читаете. - person David; 14.07.2012
comment
О, я вижу здесь проблему. Извините за неполный ответ. - person retrohacker; 14.07.2012

Подумайте о том, чтобы написать новый класс, похожий на shared_ptr<CMObject*>, и выполнить сохранение/освобождение внутри этого объекта.

person sny    schedule 14.07.2012
comment
А еще лучше, просто используйте сам shared_ptr<> — попытка заново изобрести его только закончится болью. - person ildjarn; 14.07.2012
comment
К сожалению, я переношу на кросс-платформенную систему, которая развертывается на различных системах типа Arm и X86. Стандарты C++ 11 еще не доступны для всех этих систем, поэтому я вынужден делать это по старинке. - person David; 14.07.2012
comment
@David: По старинке было бы boost::shared_ptr<> и boost::unordered_map<> - здесь все равно не нужно изобретать велосипед. :-] - person ildjarn; 15.07.2012
comment
Мы пытаемся получить ускоренную кросс-компиляцию для всех этих платформ со смешанными результатами. Я уверен, что в конце концов это произойдет, но, надеюсь, раньше, чем позже. - person David; 15.07.2012
comment
@David: FWIW, две упомянутые мной библиотеки предназначены только для заголовков, не требуют связывания и, следовательно, кросс-компиляция не требуется больше, чем просто кросс-компиляция вашего собственного приложения. - person ildjarn; 15.07.2012
comment
Я не знал об этом. Я должен скачать это и попробовать. Спасибо за совет! - person David; 15.07.2012