类就像服务器给客户开了一个玩笑,然后想尽千方百计的圆这个谎。
运算符重载
运算符重载就是C++中多态的另一种表现,目的是让类使用起来更自然。
使用方法,类内重载:
返回值 operator运算符(参数);
比如,对于类A:
A operator + (int n);
使用就可以
A tmp;
int n;
tmp = tmp + n;
但是n+tmp是错误的,因为类内重载说白了还是成员函数,运算符左面就是第一个参数,也就是对象本身,运算符右面就是重载运算符函数的参数。如果需要反过来,可以用类外重载(非成员函数重载),也就是通过友元函数。
以下10种运算符不允许重载(不允许重载的运算符):
. :成员运算符
?: :条件运算符
siezof::sizeof运算符
:: :作用域解析运算符
.* :成员指针运算符
typeid:一个RTTI运算符
const_cast:强制转换运算符
dynamic_cast:强制转换运算符
teinterpret_cast:强制转换运算符
static_cast:强制转换运算符
友元函数
友元有3种:友元函数,友元类,友元成员函数。
通过函数称为类的友元,可以赋予该函数与类的成员函数相同的访问权限,这里主要写友元函数。
为了解决上文的问题,其实大部分运算符都可以类外重载。以此来交换传参的顺序。
友元就是在成员函数最前面加个friend。
这样,这个函数就不是成员函数,就不能用成员运算符调用
虽然不是成员函数,但是他却又类作用域。
因为不是成员函数,所以编写函数定义的时候不需要加作用域限定符,不要再定义的时候加friend。
重载ostream & operator(ostream &os,A b)
{
os
当然,这个重载要作为A的友元才能方法A的私有成员数据。当然,如果A类有返回要打印的数据的函数,重载不一定必须是友元。换句话说,只要能打印出数据,是不是友元无所谓,我们重载operator TypdName();
注意:
- 转换函数必须是类方法
- 转换函数不能指定返回类型
- 转换函数不能有参数
比如:
operator double();
使用起来也比较奇葩,比如对于类A:
A tmp = 1.2;
double tt = double(tmp);
这就是为什么说更像数据类型重载而不是强制转换了。
但是还要注意的是:没有返回类型不是没有return,要不然,强制转换之后,到底赋值赋的什么呢?还是靠return控制的,只是在声明和定义中不写罢了。
当然,转换函数有了,显式隐式转换都无所谓了,因为都可以实现。
最后一点,一定要注意好转换中的二义性,比如,定义了int和double转换函数,却给一个long赋值,会怎么样呢?
如果只有一个转换函数,那么语法没有错误,int或double对long都是合法的,但如果都存在,则编译器无法判断使用哪个重载,便报错,对于这种情况,要么就再定义一个long 的转换函数,要么直接使用强制转换。
One more thing
如果转换函数和友元函数联合起来,效果是惊人的。一个可以控制类型的转换,一个可以进行运算等操作。
但是,过多的转换函数却很容易导致二义性,所以说,玩火谨防尿床。
但还是分析一下:
如果依赖隐式转换完成运算,程序更简短,定义的函数更少,出错几率也就小但是每次转换的时候都将调用转换构造函数,这增加时间和内存开销。反之,利用重载运算符,程序员需要完成的工作更多,但程序运行速度较快。