0.类声明
#pragma once
class CDog
{
public:
CDog(void);
CDog(int);
CDog(CDog &c);
virtual ~CDog(void);
static void getName();
int getItVal() const;
void setItVal(int val);
void operator++ ();
public:
int *ptr;
private:
int _itVal;
};
1.重载前置运算符 retType operator op ();
声明:void operator++ ()
定义:void CDog::operator++ ()
{
_itVal++;//_itVal 是一个Int型变量
}
但这个运算符返回空,有时我们可能会有这样的要求:
CDog a,i;
a = ++i;//这样就出问题了,因为返回空!!
重载运算符的返回类型:
1)可以创建一个临时对象并返回它
声明: CDog operator ++();
定义: CDog CDog::operator ++ ()
{
CDog tmp;
_itVal++;
tmp.setItVal(_itVal);
return tmp;//所有赋值与返回都会调用复制构造函数,产生一个临时对象,注意指针成员的问题,在这里,我们有自己的复制构造函数,对指针成员进行处理
}
2)返回无名临时对象,利用使用值初始化的构造函数构造出一个对象并返回,如下:
声明: CDog operator ++();
定义: CDog CDog::operator ++ ()
{
_itVal++;
return CDog(_itVal);//利用带参的构造函数
}
这种方法比第一种要简单,但是仍有问题,因为每一个对象的创建都在经过销毁,这样一个临时变量的存在会花销很多时间!在上面中,对象i已经存在,我们可以利用this指针返回!
3)this指针
声明: const CDog& operator ++();
定义: CDog CDog::operator ++ ()
{
_itVal++;
return *this;//返回本对象,this指针代表已经实例出的本对象
}
返回的是一个CDog的引用,所以避免创建临时对象,这个返回值必须是常量!
2.重载后置运算符
前置与后置的区别:
前置:是先加1后取值
后置:是先取值再加1,这样就有一个问题,我们必须创建一个临时对象来保存原来的值,然后再返回临时对象
如下:
int x = 5;
int a;
a = x++;//后置运算符
过程:先是 x 是 5 ,执行这句话后,a 是 5 ,但x却是6了!!这样,如果x是一个对象,就必须保存一个临时对象,然后使x的值加一,然后返回这个临时对象给a。与上面this不同,我
们返回的是一个临时对象,所以不能返回它的引用,这是因为一旦函数返回临时对象将超出作用域。
在上面的操作中,x 是本对象!!!
下面开始:
声明: const CDog operator++ (int flag);//注意,这个参数只是用来区分前后置的,不参与运算
定义: const CDog CDog::operator++ (int flag)
{
CDog tmp(*this);//上面说了,本对象是x,所以这里,this是指向x的
_itVal++; //x自己加1;
return tmp; //返回临时对象
}
3.重载加法运算符
自加是一个单目运算符,它只作用于一个对象,加法是一个双目运算符,涉及到两个对象。
例如:
a = x + y;
从这可以看出来,x + y返回的一定是一个临时对象
声明: CDog operator+ (const CDog&)
定义: CDog CDog::operator+ (const CDog& c)//在这里,this相当于x, 参数c相当于y,返回赋值给a
{
return CDog( this._itVal + c.getItVal() );//能看懂不?构造一个临时对象,这的值只当前对象与参数对象相加得到
}
4.赋值运算符
(1)要检查当前对象是否与正在被赋值的对象相同(通过对象地址)
声明:CDog& operator= (const CDog&);
定义:CDog& CDog::operator= (const CDog& c)
{
if (this == &c)
return *this;
_itVal = c.getItVal();//注意浅拷贝的问题
.....
return *this;
}
编译器默认的四个功能:一默认构造函数,默认析构函数,默认复制构造函数,默认赋值函数