1.赋值运算符重载
1.发生时机:用一个已有对象,给另一个已有对象赋值。两个对象均已创建结束后,发生的赋值行为。
2.系统默认提供赋值运算符重载,一旦自实现,则不再提供。
3.系统默认的是等位拷贝(即浅拷贝),会造成重析构,从而使内存泄漏。
4.在此情况下的等位拷贝的问题:
1.导致自身的内存泄漏( 等位拷贝是将其赋值量的地址赋给被赋值量,使被赋值量原来指向的地址没有了指向,从而导致内存泄漏。)
2.导致重析构(1中解释表示两个量指向同一个地址,从而导致其地址呗析构两次。)
3.自赋值(属于人为,即特意写出自赋值代码,如:a=a;)
5.自实现赋值运算符重载(解决等位拷贝问题)
1.被赋值量先将自己指向的地址释放掉
2.制造出一个与赋值量内存大小一样的空间,使被赋值量指向新的空间
3.最后将赋的值赋给被赋值量。
4.解决1中的自赋值问题:在进入拷贝构造时便判断是否是自身,若是则退出不做任何操作。
5.在 自实现拷贝构造器中返回语句为:return *this;其为了实现连等功功能(a=b=c)
自实现赋值运算符重载代码:
MyString &MyString::operator =(const MyString &another) { if(this->_str=another._str) return *this; delete []_str; int len=strlen(another._str); _str=new char[len+1]; strcpy(_str,another._str); return *this; }
2.+运算符重载(返回的是对象,不是引用)
重载功能:将 字符串连接在一起
实现:
1.先定义一个临时的中间类对象,用于将两个字符串连接在一起。
2.将对象中的数据成员内存释放。
3.为其重新分配新的空间(长度为两个字符串的总长度),若下面用strcpy函数则应先清空(新分配的空间有可能存放着垃圾值,而strcpy是从\0后开始拷贝,若前面有一些垃圾值,则结果会有误。),用memset(要清的内存,0,内存的长度)函数清空
4.用strcat函数将两个字符串连接在一起(先连接第一个,在连接第二个,顺序别搞反了)。
5.返回中间临时对象
String String::operator +(const String &anoter) { String temp; delete []temp._str; int len=strlen(this->_str); len +=strlen(anoter._str); temp._str=new char[len+1]; memset(temp._str,0,len+1); strcat(temp._str,this->_str); strcat(temp._str,anoter._str); return temp; }
加了memset函数的结果:
没加memset函数的结果:
3.比较运算符重载(下标运算符[]、>、<、==)
char& String::operator [](int idx) { return this->_str[idx]; } bool String::operator >(const String &another) { if(this->_str>another._str) return true; else return false; } bool String::operator <(const String &another) { if(this->_str<another._str) return true; else return false; } bool String::operator ==(const String &another) { if(this->_str==another._str) return true; else return false; }
4.const修饰符 可修饰数据成员、成员函数、类对象 1.在修饰数据成员时, 初始化位置只能在参数列表里。 被const修饰的数据成员,不能被修改 2.修饰成员函数时, 位置放在函数声明之后,实现体之前【void print() const { }】,要求在声明和定义处都要有const关键字。 意义:表示不会通过任何方法修改类数据成员,即能访问const和非const数据成员,但不能修改非const数据成员,也不能通过其类成员函数修改,只能访问const成员函数。 可构成重载 const 对象只能调用const成员函数。 非const成员对象,优先调用非const成员函数,若无,则可调用const成员函数。 3.修饰类对象 const 修饰函数,是从函数的层面,不能修改数据 const 修饰对象,是从对象的层面,不能修改数据,只能调用const成员函数
5.static修饰符(静态:静态变量,静态函数)
在C中 可修饰全局变量、局部变量
修饰全局变量:改变作用域,使其仅限用于本文件
修饰局部变量:改变生命周期(局部变量是随用隋开,用完即消,用static修饰之后与主函数生命周期一样)、存储位置(未修饰的局部变量放在栈上、被static修饰之存放data段的bss段(未初始化)或 rw段(初始化))
在C++中
在类内部,用来实现族类对象间的数据共享。
在生成对象时,普通数据成员才有空间。而static数据成员在类声明时就已经开辟了空间。
static数据成员既属于类(能用类访问),也属于对象(也能用对象访问),但终究属于类。【即:在没有对象生成时,可用类名访问static数据成员】
static修饰数据成员:在类内定义,在类外定义:类型名 类名::变量名=初值;
static修饰成员函数:只用于管理static数据成员。
static修饰的成员函数既属于类(能用类访问),也属于对象(也能用对象访问),但终究属于类。【即:在没有对象生成时,可用类名访问static成员函数】
static修饰的成员函数,因为它属于类,所以没有this指针。不能访问非static数据成员和成员函数。
6.指向类成员的指针
指向类数据成员的指针:
定义:类型名 类名::*指针
初始化:类型名 类名::*指针=&类名::非静态数据成员
指向非静态数据成员的指针在定义时必须和类相关,在使用时必须和具体的对象关联
解引用: 类对象名.*指针 或 类对象名->*指针
指向类成员函数的指针:
定义:类型名 类名::*指针(参数列表)
初始化:类型名 类名::*指针(参数列表)=&类名::非静态成员函数
解引用: 类对象名.*指针 或 类对象名->*指针(参数列表)