有两个版本,const版本和非const版本。非const版本是给没有被const关键字修饰的对象使用的,const版本是给被const关键字修饰的常对象使用的。
String.h
char& operator[](int i);
char operator[](int i) const;
String.cpp
char& String::operator [] (int i) //给非const对象使用,因此返回引用。引用意味着可以被赋值,可以出现在赋值符号的左边
{
if((0<=i) && (i<m_length))
{
return m_str[i];
}
else
{
THROW_EXCEPTION(IndexOutOfBoundsException,"parameter i is invalid...");
}
}
char String::operator[] (int i) const
{
//将当前对象的只读属性去掉,从而可以调用上面实现的非const版本,实现代码的复用。
return(const_cast<String&>(*this))[i];
}
Strng.h
bool equal(const char* l,const char* r, int len) const; //l r表示字符数组的首地址
bool startWith(const char* s) const;
bool startWith(const String& s) const;
bool endOf(const char* s) const;
bool endOf(const String& s) const;
String.cpp
bool String::equal(const char *l, const char *r, int len) const
{
bool ret = true;
for(int i=0; i<len && ret; i++)
{
ret = ret && (l[i] == r[i]);
}
return ret;
}
bool String::startWith(const char *s) const
{
bool ret = (s != NULL);
if(ret)
{
/*
*在比对之前,首先要判断一下s与字符串对象中的字符串的长度大小。
* 合法情况:s的字符串长度小于字符串对象中字符串的长度
*/
int len = strlen(s);
ret = (len < m_length) && (equal(m_str,s,len));
}
return ret;
}
bool String::startWith(const String &s) const
{
return startWith(s.m_str);
}
bool String::endOf(const char *s) const
{
bool ret = (s != NULL);
if(ret)
{
/*
*在比对之前,首先要判断一下s与字符串对象中的字符串的长度大小。
* 合法情况:s的字符串长度小于字符串对象中字符串的长度
*/
int len = strlen(s);
//需要定位到最后几个字符的起始位置,最后的这几个字符是由s决定的
char* str = m_str + (m_length - len);
ret = (len < m_length) && (equal(str,s,len));
}
return ret;
}
bool String::endOf(const String &s) const
{
return endOf(s.m_str);
}
main.cpp
int main()
{
String s = "jackson is handsome";
cout << s.startWith("jac") << endl;
cout << s.endOf("handsome") << endl;
for(int i=0; i<s.length(); i++)
{
cout << s[i] << endl;
}
return 0;
}
String.h
String& insert(int i, const char* s);
String& insert(int i, const String& s);
String.cpp
/*返回引用就是为了实现链式操作*/
String& String::insert(int i,const char* s)
{
if((0<=i) && (i<=m_length))
{
if((s != NULL) && (s[i] != '