use*_*983 6 c++ class operator-overloading
在"The C++ Programming Language"一书中,作者给出了以下示例以及几个语句:
如果仅仅返回引用并让用户决定如何处理它是不可接受的,那么定义用于读取和写入的操作符(例如[])是很困难的.
Cref,是帮助实现区分阅读和写作的下标操作符.
为什么[]难以定义何时用于读写?类Cref的定义如何帮助解决这个问题?
class String{
struct Srep;
Srep *rep;
public:
class Cref;
// some definitions here
void check (int i) const { if (i<0 || rep->sz<=i) throw Range( );}
char read( int i) const {return rep->s[i];}
void write(int i, char c){ rep=rep->get_own_copy(); rep->s[i]=c;}
Cref operator[] (int i){ check(i); return Cref(*this, i);}
char operator[] (int i) const{check(i); return rep->s{i];}
}
class String::Cref{
friend class String;
String& s;
int i;
Cref(String& ss, int ii): s(ss),i(ii) {}
public:
operator char( ) { return s.read(i);}
void operator=(char c){s.write(i,c);}
};
Run Code Online (Sandbox Code Playgroud)
如果您没有定义Cref解决此问题的类,那么您必须执行以下std::map操作:
template class <K,V> class map{
V& operator[](K const & key);
}
Run Code Online (Sandbox Code Playgroud)
这将返回一个引用,该引用必须由有效的内存位置支持,因此
std::map<string,string> m;
m["foo"];
assert(m.find("foo") != m.end());
Run Code Online (Sandbox Code Playgroud)
断言将成功(意思"foo"是,现在是地图中的有效键),即使您从未分配过某些内容m["foo"].
这种违反直觉的行为可以通过Cref示例中的类来修复- 它可以执行适当的逻辑,m["foo"]仅在分配给引用时创建,并确保m.find("foo") == m.end()在尝试读取不存在时不执行某些赋值m["foo"].
同样,在您的String类中(这是一个引用计数字符串 - 字符串共享其字符串数据,并且当您更改其数据与另一个字符串共享的字符串时创建新副本),您必须在复制时通过operator[]阅读文字.使用Cref该类,可以确保您在使用时只进行复制operator[].