[置顶] operator overloading(操作符重载,运算符重载)运算符重载,浅拷贝(logical copy) ,vs, 深拷贝(physical copy)
operator overloading(操作符重载,运算符重载) |
所谓重载就是重新赋予新的意义,之前我们已经学过函数重载,函数重载的要求是函数名相同,函数的参数列表不同(个数或者参数类型)。操作符重载也叫运算符重载,顾名思义,运算符重载就是给运算符赋予新的意义,新的使命。
1、首先要说的是,c++中不允许用户自定义运算符,只允许程序员重载运算符。
2、那些运算符可以重载?c++中绝大部分与运算符允许重载,不能重载的运算符有5类,
(1) . (成员访问运算符)。(2).* (成员指针运算符)(3)::(域运算符)
(4)sizeof (长度运算符(5):?(条件运算符/三目运算符)
3、操作符重载的意义,由于c++中不允许用户自定义运算符,所以操作符重载可以满足用户自定义的类型之间的操作运算。比如对象之间的加减乘除等操作。
4、重载运算符的规则。
(1)、重载不能改变运算符运算对象的个数(即操作数的个数)
(2)、重载不能改变运算符的优先级。
(3)、重载不能改变运算符的结合性。
(4)、重载运算符的函数不能有默认的参数,否则就改变了运算符参数的个数,与前面第(3)点矛盾。
(5)、重载的运算符必须和用户定义的自定义类型的对象一起使用,其参数至少应有一个是类对象(或类对象的引用)。也就是说,参数不能全部是C++的标准类型,以防止用户修改用于标准类型数据的运算符的性质。
(6)、用于类对象的运算符一般必须重载,但有两个例外,运算符“=”和“&”不必用户重载。
① 赋值运算符(=)可以用于每一个类对象,可以利用它在同类对象之间相互赋值。(这样的拷贝是浅拷贝(logical copy),如果
成员变量有指针的话,这样的拷贝会造成二次删除,如果要避免二次删除,那么就有必要重载 = 运算符了)
② 地址运算符&也不必重载,它能返回类对象在内存中的起始地址。
② *也不必重载,它能返回类对象在内存中的起始地址。
(7)、应当使重载运算符的功能类似于该运算符作用于标准类型数据时所实现的功能。
(8)、运算符重载函数可以是类的成员函数(如例10.2),也可以是类的友元函数,还可以是既非类的成员函数也不是友元函数的普通函数。
Eg:友元函数重载加减乘除(+ - * /)重载
#include<iostream>
#include<stdlib.h>
using namespace std;
class Complex
{
public:
Complex(float r=0,float i =0):_r(r),_i(i)
{
}
void print() const
{
cout<<" _r "<<_r<<" _i "<<_i<<endl;
}
private:
float _r;
float _i;
friend const Complex operator+(const Complex & x,const Complex & y);
friend const Complex operator-(const Complex & x,const Complex & y);
friend const Complex operator*(const Complex & x,const Complex & y);
friend const Complex operator/(const Complex & x,const Complex & y);
friend ostream & operator<<(ostream & out,const Complex & y);
};
inline const Complex operator+(const Complex & x,const Complex & y)
{
return Complex(x._r+y._r,x._i+y._i);
}
inline const Complex operator-(const Complex & x,const Complex & y)
{
return Complex(x._r-y._r,x._i-y._i);
}
inline const Complex operator*(const Complex & x,const Complex & y)
{
return Complex(x._r*y._r-x._i*y._i,x._r*y._i+x._i*y._r);
}
inline const Complex operator/(const Complex & x,const Complex & y)
{
if(y._r==0 && y._i==0)
{
exit(1);
}
float den=y._r*y._r+x._i*y._i;
return Complex((x._r*y._r+x._i*y._i)/den,(x._i*y._r-x._r*y._i)/den);
}
inline ostream & operator<<(ostream & out,const Complex & x)
{
out<<" -r "<<x._r<<endl;
out<<" _i "<<x._i<<endl;
return out;
}
int main()
{
Complex x(2,3),y(-1,3);
cout<<" x is ";
x.print();
cout<<" y is ";
y.print();
(x+y).print();
operator+(x,y).print();
(x-y).print();
operator-(x,y).print();
(x*y).print();
operator*(x,y).print();
(x/y).print();
operator/(x,y).print();
cout<<"=================="<<endl;
operator<<(cout,x);
(cout<<x)<<"______________"<<endl;
return 0;
}
成员函数 + - * / 操作符重载 |
Eg:c成员函数重载加减乘除(+ - * /)重载
#include<iostream>
#include<stdlib.h>
using namespace std;
class Complex
{
public:
Complex(float r=0,float i =0):_r(r),_i(i)
{
}
void print() const
{
cout<<" _r "<<_r<<" _i "<<_i<<endl;
}
private:
float _r;
float _i;
public:
const Complex& operator+(const Complex & y);
const Complex& operator-( const Complex & y);
const Complex& operator*(const Complex & y);
const Complex& operator/(const Complex & y);
};
inline const Complex& Complex::operator+(const Complex & y)
{
this->_r=_r+y._r;
this->_i=_r+y._i;
//(_r+y._r,_i+y._i)
return (*this);
}
inline const Complex& Complex::operator-( const Complex & y)
{
return Complex(_r-y._r,_i-y._i);
}
inline const Complex& Complex::operator*( const Complex & y)
{
return Complex(_r*y._r-_i*y._i,_r*y._i+_i*y._r);
}
inline const Complex& Complex::operator/( const Complex & y)
{
if(y._r==0 && y._i==0)
{
exit(1);
}
float den=y._r*y._r+_i*y._i;
return Complex((_r*y._r+_i*y._i)/den,(_i*y._r-_r*y._i)/den);
}
int main()
{
Complex x(2,3),y(-1,3);
cout<<" x is ";
x.print();
cout<<" y is ";
y.print();
(x.operator+(y)).print();
(x+y).print();
cout<<" x is ";
x.print();
cout<<" y is ";
y.print();
return 0;
}
>> 输入操作符重载 |
Eg:>> 输入操作符重载
#include<iostream>
#include<stdlib.h>
using namespace std;
class Complex
{
public:
Complex(float r=0,float i =0):_r(r),_i(i)
{
}
void print() const
{
cout<<" _r "<<_r<<" _i "<<_i<<endl;
}
private:
float _r;
float _i;
friend istream& operator>>(istream &in, Complex& x);
friend ostream& operator<<(ostream &out,const Complex&x);
};
istream& operator>>(istream &in, Complex& x)
{
in>>x._r>>x._i;
return in;
}
ostream& operator<<(ostream &out,const Complex&x)
{
out<<" _r = "<<x._r<<endl;
out<<" _i = "<<x._i<<endl;
return out;
}
int main()
{
Complex x(2,3),y(-1,3);
x.print();
Complex d;
cin>>d;
//operator>>(cin,x);
x.print();
return 0;
}
浅拷贝(logical
copy) vs 深拷贝(physical copy) |
//Eg:浅拷贝 #include<iostream> #include<string.h> #define MAX_CHAR 10 using namespace std; class Account { public: Account(char* name="unknown",char* mr="Miss",float f=0.0) { title=new char[strlen(name)+1]; strcpy(title,mr); strcpy(owner,name); balance=f; }
//这里并没有实现深拷贝。只是一个普通的函数,但是这里的思想和重载操作符 = 是一样的,都是单独开辟一段新的 //空间,然后再进行拷贝。~~~~ void changetitle(char* newname) { if(strlen(newname)>strlen(title)) { char* tmp=title; title=new char[strlen(newname)+1]; strcpy(title,newname); delete []tmp; } else { strcpy(title,newname); } } void changename(char* newname) { strcpy(owner,newname); } ~Account() { delete []title; title=NULL; } private: char* title; char owner[MAX_CHAR]; float balance; friend ostream& operator<<(ostream & os,Account & b); }; ostream& operator<<(ostream & os,Account & b) { os<<"who:"<<b.title<<" "<<b.owner<<" "<<b.balance<<endl; return os; } int main() { Account acc("zhanger gou","Mr",1000); Account ac1; cout<<acc; cout<<ac1; ac1=acc; cout<<ac1; cout<<acc; ac1.changename("er gou"); cout<<acc; cout<<ac1; ac1.changetitle("Re"); cout<<acc; cout<<ac1; return 0; }
1)、两个对象的指针指向同一块空间,改变其中一个,两个都改变。
2)、两个对象的指针指向同一块空间,不知道谁负责释放指向的空间,很容易造成二次删除。
重载操作符 =
首先判断是不是自拷贝
第二步 删除指针指向的原来的空间
第三步 开辟新的空间
第四步 拷贝内容,注意的是要将所有内容都拷贝一遍,否则的话会遗漏,其他的会被赋值成默认值。
第五步 返回自身 *this
//Eg:深拷贝 #include<iostream> #include<string.h> #define MAX_CHAR 10 using namespace std; class Account { public: Account(char* name="unknown",char* mr="Miss",float f=0.0) { title=new char[strlen(name)+1]; strcpy(title,mr); strcpy(owner,name); balance=f; } void changetitle(char* newname) { if(strlen(newname)>strlen(title)) { char* tmp=title; title=new char[strlen(newname)+1]; strcpy(title,newname); delete []tmp; } else { strcpy(title,newname); } } void changename(char* newname) { strcpy(owner,newname); } ~Account() { delete []title; title=NULL; } private: char* title; char owner[MAX_CHAR]; float balance; friend ostream& operator<<(ostream & os,Account & b); public: Account& operator=(const Account& a) { if(this!=&a) { delete[] title; title=new char[strlen(a.title)+1]; strcpy(title,a.title); strcpy(owner,a.owner); balance=a.balance; } return *this; } }; ostream& operator<<(ostream & os,Account & b) { os<<"who:"<<b.title<<" "<<b.owner<<" "<<b.balance<<endl; return os; } int main() { Account acc("zhanger gou","Mr",1000); Account ac1; cout<<acc; cout<<ac1; ac1=acc; cout<<ac1; cout<<acc; ac1.changename("er gou"); cout<<acc; cout<<ac1; ac1.changetitle("Re"); cout<<acc; cout<<ac1; return 0; }