我们首先来看看C++库中的string类有什么功能。
string s1("hel"); string s2("lo"); string s3; s3 = s1 + s2; cout << s3 << endl;
我们就先看看上面这些例子,首先我们可以用一个字符串给s1对象初始化,我们可以用+号连接两个字符串,同时我们还可以用=号直接给s3对象赋值,最后还可以用cout直接输出这个对象中的字符串。
我们自己写个类来实现这些功能。
实现这些功能需要注意的
1、要注意字符串的拷贝,深拷贝。
2、注意内存的动态分配和释放。
3、运算符重载的使用。
现在我们就来看看怎么编写这些功能,看代码。
#include <iostream> #pragma warning(disable:4996) //由于在vs2015使用strcpy会报错,所以加了这一句话 using namespace std; class MyString { public: MyString(char *s); MyString(const MyString &s); //拷贝构造函数 MyString(); //不带参数的构造函数 ~MyString(); //析构函数 MyString& operator=(const MyString &s); //=号运算符重载 MyString operator+(const MyString &s);//+号运算符重载 char operator[](int i);//[]运算符重载 bool operator<(const MyString &s);//<运算符重载 bool operator>(const MyString &s);//>运算符重载 bool operator==(const MyString &s);//==运算符重载 bool operator!=(const MyString &s);//!=运算符重载 private: char *str; //友元函数 friend ostream& operator<<(ostream &out, MyString &s);//重载左移运算符 friend istream& operator >> (istream &in, MyString &s); //重载右移运算符 }; //不带参数的构造函数 MyString::MyString() { this->str = new char[1]; str[0] = '\0'; } //带一个参数的构造函数 MyString::MyString(char *s) { str = new char[strlen(s) + 1]; strcpy(this->str, s); } //拷贝构造函数 MyString::MyString(const MyString &s) { str = new char[strlen(s.str) + 1]; strcpy(this->str, s.str); } //析构函数 MyString::~MyString() { if (this->str != NULL) { delete[] this->str; } } //+号运算符重载 MyString MyString::operator+(const MyString &s) { MyString p; p.str = new char[strlen(this->str) + strlen(s.str) + 1]; strcpy(p.str, this->str); strcat(p.str, s.str); return p; } //=号运算符重载 MyString& MyString::operator=(const MyString &s) { if (this == &s) { return *this; } if (this->str != NULL) { delete[] this->str; } this->str = new char[strlen(s.str) + 1]; strcpy(this->str, s.str); return *this; } //[]运算符重载 char MyString::operator[](int i) { int len = strlen(this->str) - 1; if (i > len) { return ('\0'); } else { return (this->str[i]); } } //<运算符重载 bool MyString::operator<(const MyString &s) { int ret; ret = strcmp(this->str, s.str); if (ret < 0) return true; else return false; } //>运算符重载 bool MyString::operator>(const MyString &s) { int ret; ret = strcmp(this->str, s.str); if (ret > 0) return true; else return false; } //==运算符重载 bool MyString::operator==(const MyString &s) { int ret; ret = strcmp(this->str, s.str); if (ret == 0) return true; else return false; } //!=运算符重载 bool MyString::operator!=(const MyString &s) { int ret; ret = strcmp(this->str, s.str); if (ret != 0) return true; else return false; } //左移运算符重载 ostream& operator<<(ostream &out, MyString &s) { out << s.str; return out; } //右移运算符重载 istream& operator>>(istream &in, MyString &s) { char p[50]; in.getline(p, 50); s = p; return in; } int main() { MyString m1("hello"); MyString m2("world"); MyString m3; m3 = m1 + " " + m2; cout << "m3 = " << m3 << endl; MyString m4(m3); cout << "m4 = " << m4 << endl; cout << "m1[1] = " << m1[1] << endl; cout << (m1 < m2) << endl; cout << (m1 > m2) << endl; cout << (m1 == m3) << endl; system("pause"); return 0; }
这里主要讲解的是拷贝构造函数、赋值运算符重载、+号运算符重载和[]运算符重载的写法。
拷贝构造函数
MyString::MyString(const MyString &s) { str = new char[strlen(s.str) + 1]; strcpy(this->str, s.str); }
拷贝构造函数的第一个参数时这个类的一个引用,拷贝构造函数主要完成两个任务:①是给类中的str动态分配空间,用来容纳传入的s对象中的str字符串。②将s对象中的str拷贝到被初始化对象的str中。
赋值函数(=号运算符重载)
MyString& MyString::operator=(const MyString &s) { if (this == &s) { return *this; } if (this->str != NULL) { delete[] this->str; } this->str = new char[strlen(s.str) + 1]; strcpy(this->str, s.str); return *this; }
首先要判断这两个对象是否相同,如果相同就返回这个对象本身,如果不同就得判断原本的对象中给str分配的空间有没有被释放,如果没有就得将其内存释放,然后重新分配一个能够容纳用于赋值的对象中str的空间。然后再将这个str拷贝到被赋值的str中。
[]运算符重载
char MyString::operator[](int i) { int len = strlen(this->str) - 1; if (i > len) { return ('\0'); } else { return (this->str[i]); } }
在写[]运算符重载的时候我们要注意下标的越界问题,所以我们得先判断要取出的下标是否越界,如果越界我就让其返回一个空字符。否则我们就返回相应的元素。
+号运算符重载
MyString MyString::operator+(const MyString &s) { MyString p; p.str = new char[strlen(this->str) + strlen(s.str) + 1]; strcpy(p.str, this->str); strcat(p.str, s.str); return p; }我们定义一个局部对象,用来存放连接后的字符串,首先要给它分配一个能够容纳两个字符串的空间,然后用strcpy将第一个字符串复制到p中,再用strcat连接这两个字符串。