重载赋值运算符=
- 赋值运算符重载用于对象数据的复制
- operator= 必须重载为成员函数
- 重载函数原型为:
类型 & 类名 :: operator= ( const 类名 & ) ;
结论:
- 先释放旧的内存
- 返回一个引用
- =操作符 从右向左
//obj3 = obj1; // C++编译器提供的 等号操作 也属 浅拷贝
// obj4 = obj3 = obj1
//obj3.operator=(obj1)
Name& operator=(Name &obj1)
{
//1 先释放obj3旧的内存
if (this->m_p != NULL)
{
delete[] m_p;
m_len = 0;
}
//2 根据obj1分配内存大小
this->m_len = obj1.m_len;
this->m_p = new char [m_len+1];
//3把obj1赋值给obj3
strcpy(m_p, obj1.m_p);
return *this;
}
*为什么operator=返回一个reference to this ?
为了实现连续赋值,赋值操作符必须返回一个引用指向操作符的左侧实参。
这是你为class实现赋值操作符必须遵循的协议。
这个协议不仅适用于标准的赋值形式,也适用于+=、-=、*=等等。
注意,这只是一个协议。如果不遵循它,可能代码一样通过编译。
然而这份协议被所有内置类型和标准程序库所提供的类型如string、vector等所遵守。
因此除非你有一个标新立异的好理由,不然还是随众吧。
重载数组下标运算符 []
重载 [] 和 () 运算符:
- 运算符 [] 和 () 是二元运算符
- [] 和 () 只能用成员函数重载,不能用友元函数重载
重载下标运算符 []
[] 运算符用于访问数据对象的元素
重载格式 类型 类 :: operator[] ( 类型 ) ;
设 x 是类 X 的一个对象,则表达式:
x [ y ] 可被解释为 x . operator [ ] ( y )
重载函数调用符 ()
() 运算符用于函数调用
重载格式 类型 类 :: operator() ( 表达式表 ) ;
例1
设 x 是类 X 的一个对象,则表达式:
x ( arg1, arg2, … )
可被解释为 x . operator() (arg1, arg2, … )
//例2:用重载()运算符实现数学函数的抽象
#include <iostream>
class F
{ public :
double operator ( ) ( double x , double y ) ;
} ;
double F :: operator ( ) ( double x , double y )
{ return x * x + y * y ; }
void main ( )
{
F f ;
f.getA();
cout << f ( 5.2 , 2.5 ) << endl ; // f . operator() (5.2, 2.5)
}
比较普通成员函数
//例3 用重载()运算符实现 pk 成员函数
#include <iostream.h>
class F
{ public :
double memFun ( double x , double y ) ;
} ;
double F :: memFun ( double x , double y )
{ return x * x + y * y ; }
void main ( )
{
F f ;
cout << f.memFun ( 5.2 , 2.5 ) << endl ;
}
指针运算符(*、->)重载
class Person{
public:
Person(int param){
this->mParam = param;
}
void PrintPerson(){
cout << "Param:" << mParam << endl;
}
private:
int mParam;
};
class SmartPointer{
public:
SmartPointer(Person* person){
this->pPerson = person;
}
//重载指针的->、*操作符
Person* operator->(){
return pPerson;
}
Person& operator*(){
return *pPerson;
}
~SmartPointer(){
if (pPerson != NULL){
delete pPerson;
}
}
public:
Person* pPerson;
};
void test01(){
//Person* person = new Person(100);
//如果忘记释放,那么就会造成内存泄漏
SmartPointer pointer(new Person(100));
pointer->PrintPerson();
}
为什么不要重载&&和||操作符
理论知识:
- &&和||是C++中非常特殊的操作符
- &&和||内置实现了短路规则
- 操作符重载是靠函数重载来完成的
- 操作数作为函数参数传递
- C++的函数参数都会被求值,无法实现短路规则
内置版本的&&和||首先计算左边的表达式,如果这完全能够决定结果,就无需计算右边的表达式了–而且能够保证不需要。
class Complex{
public:
Complex(int flag){
this->flag = flag;
}
Complex& operator+=(Complex& complex){
this->flag = this->flag + complex.flag;
return *this;
}
bool operator&&(Complex& complex){
return this->flag && complex.flag;
}
public:
int flag;
};
int main(){
Complex complex1(0);
Complex complex2(1);
//原来情况,应该从左往右运算,左边为假,则退出运算,结果为假
//这边却是,先运算(complex1+complex2),导致,complex1的flag变为complex1+complex2的值, complex1.a = 1
// 1 && 1
//complex1.operator&&(complex1.operator+=(complex2))
if (complex1 && (complex1 += complex2)){
cout << "真!" << endl;
}
else{
cout << "假!" << endl;
}
return EXIT_SUCCESS;
}
根据内置&&的执行顺序,我们发现这个案例中执行顺序并不是从左向右,而是先右猴左,这就是不满足我们习惯的特性了。由于complex1 += complex2先执行,导致complex1 本身发生了变化,初始值是0,现在经过+=运算变成1,1 && 1输出了真。