Как различать операции чтения / записи при использовании оператора []

Мне нужно написать класс с перегруженным оператором [], который будет вести себя иначе, когда оператор [] используется для чтения или записи данных. Чтобы дать практический пример того, чего я хочу достичь, скажем, мне нужно написать реализацию класса с именем PhoneBook, который можно использовать следующим образом:

PhoneBook phoneBook(999999); // 999999 is the default number which should be
                             // used when calling someone who is not in the phone book

phoneBook["Paul"] = 234657;  // adds Paul's number
phoneBook["John"] = 340156;  // adds John's number

// next line should print Paul's number 234657
cout << "To call Paul dial " << phoneBook["Paul"] << endl;
// next line should print John's number 340156
cout << "To call John dial " << phoneBook["John"] << endl;
// next line should print 999999 because Frank is not in the phone book
cout << "To call Frank dial " << phoneBook["Frank"] << endl;

Проблема в том, что при использовании

phoneBook["Frank"]

я не хочу добавлять в телефонную книгу запись для Фрэнка, иначе было бы легко реализовать решение, основанное на std :: map.

Я не нашел в Интернете стандартного способа добиться этого, поэтому Поразмыслив, я пришел к следующему решению, в котором оператор [] возвращает «временный объект» с именем PhoneNumber. PhoneNumber затем используется для различения операций чтения / записи:

#include <iostream>
#include <string>
#include <map>

using namespace std;

class PhoneBook{
private:
    map<string, int> data_; // stores phone numbers
    int defaultNumber_; // default number returned when no matching name is found

public:
    PhoneBook(int defaultNumber) :
        defaultNumber_(defaultNumber) {}

    // Searches in the phone book for a name. If the name is found it returns
    // the corresponding number. If the name is not found it returns defaultNumber_
    int read(string name){
        map<string, int>::iterator it = data_.find(name);
        if (it==data_.end()){
            return defaultNumber_;
        } else {
            return it->second;
        }
    }

    // Forwarding function to map operator []. It is not really necessary but it is added for clarity
    int& write(string name){
        return data_[name];
    }

    // Forward declaration of the "temporary object" returned by operator []
    // See declaration below
    class PhoneNumber;

    PhoneNumber operator[](string name){
        return PhoneNumber(this, name);
    }

    class PhoneNumber{
        friend class PhoneBook;
    private:
        PhoneBook* const phoneBook_;
        string name_;

        // Constructors are private so that PhoneNumber can be used only by PhoneBook
        // Default constructor should not be used
        PhoneNumber() :
            phoneBook_(NULL) {}

        PhoneNumber(PhoneBook* phoneBook, string name) :
            phoneBook_(phoneBook), name_(name) {}

    public:
        // conversion to int for read operations
        operator int (){
            return phoneBook_->read(name_);
            }

        // assignment operator for write operations
        const int& operator = (const int& val){
            return phoneBook_->write(name_) = val;
        }
    };
};

int main(){
    PhoneBook phoneBook(999999);

    phoneBook["Paul"] = 234657;
    phoneBook["John"] = 340156;

    cout << "To call Paul dial " << phoneBook["Paul"] << endl;
    cout << "To call John dial " << phoneBook["John"] << endl;
    cout << "To call Frank dial " << phoneBook["Frank"] << endl;

    return 0;
}

Класс PhoneBook ведет себя так, как я хотел бы, и программа печатает:

To call Paul dial 234657
To call John dial 340156
To call Frank dial 999999

Я хотел бы задать вам несколько вопросов:

  1. Есть ли лучший способ получить класс ведет себя как класс, который я закодировал?
  2. Есть ли у метода, который я использую, имя, чтобы я мог искать дополнительную информацию о нем?
  3. Видите ли вы какие-либо недостатки / возможные улучшения в моем решении?

В библиотека, которую я пишу, что обеспечивает поведение, которое я получил для PhoneBook :: operator [] в подобной ситуации это действительно важно и мне очень хотелось бы знать, что вы думаете о моей проблеме.

Спасибо!

8
задан carlo 17 February 2012 в 15:19
поделиться