C++第十一章笔记

2014/11/21 posted in  C++

类就像服务器给客户开了一个玩笑,然后想尽千方百计的圆这个谎。

运算符重载

运算符重载就是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

如果转换函数和友元函数联合起来,效果是惊人的。一个可以控制类型的转换,一个可以进行运算等操作。

但是,过多的转换函数却很容易导致二义性,所以说,玩火谨防尿床。

但还是分析一下:

如果依赖隐式转换完成运算,程序更简短,定义的函数更少,出错几率也就小但是每次转换的时候都将调用转换构造函数,这增加时间和内存开销。反之,利用重载运算符,程序员需要完成的工作更多,但程序运行速度较快。