使用运算符[]时如何区分读/写操作
How to distinguish read/write operations when using operator[]
我需要编写一个带有重载运算符[]的类,当使用运算符[]读取或写入数据时,该运算符具有不同的行为。为了给出一个我想要实现的实际例子,假设我必须编写一个名为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"]
我不想在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[]获得的行为在类似的情况下真的很重要,我真的很想知道你对我的问题有什么看法。
谢谢!
您提出的是这个问题的标准解决方案。通常称为代理模式或代理习惯用法,以及返回称为代理。(由于它是一个嵌套类,因此只需调用则CCD_ 1通常是足够的。)
我认为您可以实现两个版本的运算符[],一个带有const修饰符,另一个没有。如果你有一个对象,比如PhoneBook phoneBook(999999);
,如果phoneBook是const对象,那么只能调用operator [] const
。如果phoneBook是非常量对象,则调用默认的operator []
。如果要在给定非常量对象的情况下调用operator [] const
,可以添加类似static_cast<const PhoneBook&>(phoneBook)->operator[...]
的强制转换。
#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) {}
int operator [] (const string& name) const
{
map<string, int>::const_iterator it = data_.find(name);
if (it == data_.end())
{
return defaultNumber_;
}
else
{
return it->second;
}
}
int& operator [] (const string& name)
{
return data_[name];
}
};
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 " << static_cast<const PhoneBook&>(phoneBook)["Frank"] << endl;
return 0;
}
- 为什么在popback()操作之后,它仍然打印完整的矢量
- 重载操作程序时出错>>用于类中的字符串 memebr
- 函数何时会在c++中包含stack_Unwind_Resume调用
- Mix_Init和Mix_OpenAudio SDL之间的区别是什么
- 对字符串进行位操作
- Python中的for循环与C++有何不同
- 我可以在 C++ 中的函数体之外进行操作吗?
- MPI突然停止了对多个核心的操作
- 如何在信号处理程序和普通函数中对全局变量进行互斥读写操作
- 对字符数组中的元素执行逐位操作
- 如何在directx/c++中进行平移/缩放操作
- 逐位操作的隐式类型转换
- 为什么一个向量上的多线程操作很慢
- 排序时无法执行交换操作.我做的时候它会崩溃.为什么
- 位移操作和位掩码未检测到重复字符
- 如何进行特定的位操作?
- 当我们进行一些操作时,应该使用什么'std::string'或'std::stringstream'?
- 字符串操作 - 字符计数
- 此代码中的操作流程是什么?C/C++.
- 复制和交换习惯用法与移动操作之间的交互