c++基础知识
从一个基本的CMyString类讲起,分析了
构造函数
拷贝构造函数
析构函数
"="、"+="、"+"、左"++"、右"++"操作符重载
"<<"输出流友元函数重载
1、实现过程要关注内存泄露(析构)、非法输入值处理(“赋值重载”)、内存溢出异常处理(“赋值”重载)。
2、操作符重载特别注意返回值类型和返回方式
面向对象的三大特征:封装、继承和多态。多态特征将在工厂模式里强调。
class CMyString { public: CMyString(const char *pData = NULL) { /* 构造函数 作用:完成对象的初始化 调用顺序: a. 静态成员对象的构造函数。因为静态成员是与类直接相关的,在类内声明,在类的外部定义,并且只初始化一次。 b. 抽象基类的构造函数(按继承的顺序) c. 虚拟基类的构造函数(按继承的顺序) d. 非虚拟基类的构造函数(按继承的顺序) e. 非静态成员对象的构造函数(按声明的顺序) f. 调用类的构造函数。 */ if (pData == NULL) { m_pData = new char[1]; m_pData[0] = ‘\0‘; } else { //字符串数组的拷贝拷贝方式 int length = strlen(pData); m_pData = new char[length + 1]; strcpy(m_pData, pData); } } CMyString(const CMyString& str) { /* * 拷贝构造函数 * 1、深拷贝与浅拷贝 * 当类成员变量为指向堆空间的指针时,需要采用深拷贝,防止两个对象之间的干扰 * 2、深拷贝过程 * 为类成员指针分配新的堆上空间 * 执行内容拷贝 * */ int length = strlen(str.m_pData); m_pData = new char[strlen(str.m_pData) + 1]; strcpy(m_pData, str.m_pData); } ~CMyString(void) { /* * 析构函数 * 1、默认析构函数 * 2、当类成员使用堆上空间时,需要自定义析构函数,防止内存泄露 */ delete [] m_pData; } CMyString& operator=(const CMyString& str) { /* * =操作符重载 * 1、要点 * a. 返回类型声明为该类型的引用,并且在函数结束前返回对象自身的引用(*this) * b. 传入参数为常量引用 * c. 拷贝时首先需要释放堆上空间,防止内存泄露 * d. 判断参数对象与当前对象是不是同一个对象 * 2、重载:匹配同名函数的参数列表,返回值类型不在考虑范围 * 3、成员函数参数列表隐含了this指针,指向当前对象 */ if (this == &str) { //判断参数对象与当前对象是不是同一个对象 return *this; } //释放堆上空间,防止内存泄露 delete [] m_pData; m_pData = NULL; int length = strlen(str.m_pData); m_pData = new char[length + 1]; //bug: 当内存溢出时,抛出异常,对象失效 strcpy(m_pData, str.m_pData); //返回对象自身的引用 return *this; } CMyString& operator += (CMyString& rhs) { /* * +=操作符重载 * 1、返回当前类型的引用,函数结束时返回当前实例的引用*this */ CMyString temp; //定义临时变量,防止内存溢出而抛出异常 int length; length = strlen(m_pData) + strlen(rhs.m_pData); temp.m_pData = new char[length + 1]; strcpy(temp.m_pData, m_pData); strcat(temp.m_pData, rhs.m_pData); //字符串的拼接 char *pTemp = m_pData; m_pData = temp.m_pData; temp.m_pData = pTemp; //将当前实例的堆空间赋值给临时变量,在函数退出时析构 return *this; } CMyString operator + (CMyString& rhs) { /* * + 操作符重载 * 返回右值,也即将临时对象返回 * 返回过程: * a. 调用拷贝构造函数,生成匿名临时对象,用于返回 * b. 析构局部对象 */ CMyString ret; int length; length = strlen(m_pData) + strlen(rhs.m_pData); ret.m_pData = new char[length + 1]; strcpy(ret.m_pData, m_pData); strcat(ret.m_pData, rhs.m_pData); return ret; } CMyString& operator ++() { /* * 前加 * 返回引用,作为左值 */ int length; char *pTemp = m_pData; length = strlen(m_pData) * 2; m_pData = new char[length + 1]; strcpy(m_pData, pTemp); strcat(m_pData, pTemp); delete [] pTemp; return *this; } CMyString operator ++(int rhs) { /* * 后加 * 形参:标识重载函数 * 返回值:返回对象,作为右值 */ CMyString ret = *this; int length; char *pTemp = m_pData; length = strlen(m_pData) * 2; m_pData = new char[length + 1]; strcpy(m_pData, pTemp); strcat(m_pData, pTemp); delete [] pTemp; return ret; } //友元 // 输出流重载 // 作用:扩展外部函数的访问权限 friend ostream& operator<< (ostream& os, const CMyString& str); private: char *m_pData; }; //友元函数的实现 ostream& operator<< (ostream& os, const CMyString& str) { os << str.m_pData; return os; }