一、赋值运算符的重载
对于任何一个类,如果用户没有定义赋值运算符函数,那么系统会为其生成一个默认的赋值运算符函数,在对应的数据成员之间赋值,一般情况下默认的赋值元素运算符函数还能满足用户需求,但是,当类中含有指针型的数据成员时候,会出现如下问题:比如 arry1 = arry2;
(1)会引起原来对象内存的泄漏,就会引起arry1的内存泄漏;在定义arry1时,构造函数根据给出的数组的上下界为arry1动态申请一块空间,在空间的首地址存储在数据成员storage中,当执行arry1 = arry2时,默认的赋值运算符函数,只是将arry1的指针也指向了arry2内存空间;那么原来的内存空间本来是由storage指向的,现在storage指向了arry2,那么它被丢了,造成内存泄漏;
(2)俩个对象的操作会相互影响;因为arry1 和 arry2的空间都是arry2的空间;
(3)当俩个对象析构时,后面析构的那个对象会出错,因为它指向的那块内存已经被前一个对象析构掉了;
#include<iostream>
#include<vld.h>
#include<string.h>
using namespace std;
class Array
{
public:
Array(int n)
{
cout<<"Array()"<<endl;
str = new char[n];
for(int i =0;i< n;++n)
{
str[i] = 0;
}
}
Array& operator=(const Array& a)
{
cout<<"operator"<<endl;
if(this == &a)return *this;
delete []str;
int length = strlen(a.str);
str = new char[length];
return *this;
}
~Array()
{
delete []str;
}
private:
char * str;
};
int main()
{
Array arry1(3);
Array arry2(4);
arry1 = arry2;
return 0;
}
问题1:为什么已经将参数的值赋值给了当前对象,还需要返回*this值呢?
答:在C++中,赋值是一种运算,它可以构成一个表达式,而且表达式的值是左边对象的值,所以赋值运算符函数必须返回赋给左边对象的值;它方便在一次给另外一个对象赋值:arry3 = arry1 = arry2;
二、下标运算符的重载[]
下标运算符是一个二元运算符,第一个运算数是当前对象,第二个运算数是下标;C++规定下标运算符的重载必须重载成成员函数;定义式:数组元素类型 &operator[] (int index);
三、++和--的重载
++ 和--都是一元运算符,他们都可以被重载成成员函数或者友元函数,因为这俩个对象改变运算对象的状态,更倾向于作为成员函数;
++和--有俩种用法:作为前缀使用了,返回的是修改以后对象的值;作为后缀使用时,返回的是修改以前对象的值;为此,对于++和--运算,每个运算符都必须提供俩个重载函数,一个处理前缀,一个处理后缀;但是,前缀函数和后缀函数的参数的个数和参数的类型完全一样,所以普通的函数重载无法区分这里个函数;
C++规定后缀运算重载函数接受一个额外(无用的)int形式参数,这样就把前缀和后缀区分开了;
定义如下:假设有一个计数器类Counter;
Counter & Counter::operator++();
Counter Counter::operator++(int x);
为什么前缀返回的是counter的引用?后缀返回的是非引用呢?
因为前缀++返回的是当前对象的引用(也就是刚刚自增后的对象),因为当前对象*this是作为Counter&返回的,这样可以使得前缀自增的对象可以作为左值来使用(可以给变量赋值);
后缀的++,为了返回自增前的对象,我们定义了一个零时对象,零时对象在函数结束之后就消失了了,声明成非引用,在临时对象消失之前它会将自己给系统的零时变量,这样这个零时变量的值就不会无效,但是,如果声明成引用,在函数结束后,他就消失了,那么返回的引用将是一个无效空间;
四、输出输入运算符重载
1、输出运算符重载<<重载:他有俩个参数第一个是ostream类的引用,第二个参数是当前类的常量对象的引用;
ostream & operator<<(ostream &os,const classType &obj)
{
os <<"要输出的内容";
return os;//为的是这中情况:cout<<r<<k;
}
istream & operator>>(istream &is,classtype &obj)
{
is >>对象的数据成员;
return is;
}
#include<iostream>
#include<vld.h>
#include<string.h>
using namespace std;
class Array
{
public:
friend ostream & operator<<(ostream &os,const Array & a)
{
os<<a.num;
return os;
}
friend istream & operator>>(istream &is,Array &a)
{
is>>a.num ;
return is;
}
Array():num(0)
{}
/*Array(int n)
{
cout<<"Array()"<<endl;
str = new int[n];
for(int i =0;i< n;++n)
{
str[i] = 0;
}
}*/
Array(int x)
{
num = x;
}
Array& operator=(const Array& a)
{
cout<<"operator"<<endl;
if(this == &a)return *this;
delete []str;
//int length = strlen(a.str);
int length = sizeof(a)/sizeof(int);
str = new int[length];
return *this;
}
int & operator[](int index)
{
return str[index];
}
~Array()
{
//delete []str;在不是赋值函数的时候应该屏蔽点,否则出现内存错误
}
private:
int * str;
int num;
};
int main()
{
Array arry3;
/*Array arry1(3);
Array arry2(4);
arry1 = arry2;*/
//Array arry3(3);
cin>>arry3;
//cout<<arry3[0]<<endl;
/*for(int i =0;i<3;++i)
{
cin>>arry3[i];
}
for(int i=0;i<3;++i)
{
cout<<arry3[i];
}*/
cout<<arry3<<endl;
return 0;
}