运算符重载,感觉实际中很少用,直接上代码:
#include<iostream>
using namespace std;
class OperatorTest
{
int value;
public:
OperatorTest(int i) : value(i)
{
}
~OperatorTest()
{
}
int GetValue();
//当对象还没创建时,需要对对象初始化(调用合适的构造函数),否则就使用“=”
//“=”仅是成员函数,这样是为了防止重定义已有的“=”,即一般的赋值
OperatorTest& operator=(const OperatorTest& t)
{
if(this == &t) //检查一下是否对象自己
{
return *this;
}
value = t.value;
return *this;
}
const OperatorTest& operator+=(const OperatorTest& t)
{
value += t.value;
return *this;
}
//非成员运算符要声明成friend,当调用该函数的对象是别的类对象的话,即左
//侧运算符是其他类的对象则需要声明成friend
friend ostream& operator<<(ostream& out,const OperatorTest& t)
{
out<<"value :"<<t.value<<endl;
return out;
}
//不返回const的,因为返回的对象可能要用于调用其他成员函数(如 (a+b).GetValue())
//如果用了const,则要保证调用的函数也是const,但是如果不会按上面的使用,也可以返回const
OperatorTest operator+(const OperatorTest& t)
{
//这里的用法就是所谓的“返回值优化用法,当编译器看到如此使用时,知
//道对创建的对象没有其他需求,只是返回,直接把对象创建在外部返回值
//的内存单元,只是调用普通的构造函数,(并没有创建真正的局部对象)而
//且不会调用析构函数(推测是编译器对其进行回收),这样比创建一个临时
//的局部变量,然后返回它更节省资源
return OperatorTest( value + t.value);
}
//声明成friend 是把此函数定义成全局函数,其他对象可以调用。
//全局重载运算符便利之一是在全局版本版本中对左右操作数都可以进行自动
//类型转换,而成员版本必须保证左操作数是正确的对象。
friend OperatorTest operator-(const OperatorTest& a,const OperatorTest& b)
{
return OperatorTest(a.value - b.value);
}
private:
//拷贝构造函数私有,使类外不能调用拷贝构造函数
OperatorTest(const OperatorTest &t)
{
cout<<"can not happen\n";
}
};
int OperatorTest::GetValue()
{
return value;
}
int main()
{
OperatorTest p1(2); //调用普通构造函数进行初始化
OperatorTest p3(4);
OperatorTest p2 = p1; //p2还没创建需要调用构造函数进行初始化,这里调用的是拷贝构造函数
p1 = p2; //对象都已经创建,这里调用operator=
p3 = p1 + p2; //调用operator+
p3 = p2 - p1; //调用operator-
p3 = 10 - p1; //operator-有全局版本,10进行自动类型转换,转换成OperatorTest类型,所以成功。
p3 = p2 + 10; //调用operator+,左侧是对象,10(通过构造函数)转换成OperatorTest类型。
//p3 = 10 + p2;//不行。左侧是int,不是正确的类型,编译出错。
}