Мне нужно написать класс с перегруженным оператором [], который будет вести себя иначе, когда оператор [] используется для чтения или записи данных. Чтобы дать практический пример того, чего я хочу достичь, скажем, мне нужно написать реализацию класса с именем 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
Я хотел бы задать вам несколько вопросов:
В библиотека, которую я пишу, что обеспечивает поведение, которое я получил для PhoneBook :: operator [] в подобной ситуации это действительно важно и мне очень хотелось бы знать, что вы думаете о моей проблеме.
Спасибо!