关于c++说一句:不要觉得必须使用所有特性,不要在试图使用所有特性。只要满足需求即可。C++是工具。少有人敢说精通C++
运算符重载:就是让运算符能够像操作基本类型一样操作自己定义的类。
重载运算符就把运算符看成函数名就好了:operator+
。这个就当做函数名。然后利用的时候就kobe+james就好了。看本质上运算符就是一种函数,对对象进行操作。在运算符表示法中,运算符左侧为调用运算的对象,右侧的为参数传递对象。
运算符重载有一些限制,不过我觉得一般能重载的运算符足够我用,所以就不列出了。书中有个表格。
11.3友元
之前说过,对于类的私有部分,只有公有方法能够访问。这种限制有点死。
所以提供了友元这种访问方式,友元有三种:
1、友元函数
2、友元类
3、友元成员函数
这里先只介绍友元函数。
创建友元函数:
第一步:将其原型放入类声明中,并在原型声明前加上friend。
第二步:在定义cpp中,友元函数的定义前不要使用类限定(也好理解,友元函数并不是类成员函数),也不要使用friend关键字。
注意两点:
1、虽然友元函数声明在类声明中,但是不是类成员函数,因此不能用.或者->运算符调用。
2、友元函数与成员函数访问权相同,都可以访问private成员。
最最最常用的友元就是重载<<运算符,让其能像基本类型一样用cout<<
对其输出显示,而不是想之前一样傻了吧唧的定义show()函数。
//student.h
class Student
{
...
friend ostream& operator<<(ostream& os, const Student& s); //这里发现函数后并没有const,因为这就是一个函数,不是类的成员函数,没有隐式调用的对象,这个函数调用的对象只有一个s和os。
//head.cpp
ostream& operator<<(ostream& os, const Student& s)
{
os <<s.name <<s.age;
return os;
}
//main.cpp
cout<<kobe<<endl;//在用的时候,就能像其他类型一样,标准输出了。是不是美滋滋~
这里返回的是标准输出流对象引用:ostream&,这样就可以成串的输出了。不然只能单个用。
11.6类的自动转换
假如一个类的构造函数只需要一个参数:Stonewt(double lbs);
在使用时,就有可能这样:
Stonewt mycat;
mycat = 16.6;
看起来就像将double类型的16.6转换成了Stonewt类型的mycat。等号赋值的时候进行隐式的类型转换。
有时不希望隐式的转换,因为有可能引起错误或误会。在构造函数前加上explicit关键字即可:explicit Stonewt(double lbs);
这样就将隐式转换关闭了,但是显式强制类型转换还是可以的:
mycat = 16.6;//不可以了!
mycat = Stonewt(16.6);//这样或者
mycat = (Stonewt)16.6;//这样也行。。
上面的构造函数,只是定义了其他类型向本类类型转换,如果需要进行相反操作呢?将本类类型,转换成其他类型。此时需要用到转换函数。
还是上方的Stonewt类:
//在类声明中添加如下成员函数:
operator int();
operator double();
OK ,灰常简单~有三个点:
1、转换函数必须是类成员方法。
2、转换函数不能指定返回类型。(很明显返回类型是确定的,就是此类本身)
3、转换函数不能有参数。(也好理解,参数就一个,然后类型还被指定了,就不要写了)
当然转换函数也有隐式转换这个问题:int a = mycat;
同样explicit也是适用的:
explicit operator int();
explicit operator double();
声明成这样的话,上面的隐式转换将不允许,必须要显示强制转换:int a = int(mycat);
,同理,括号扩int也是可以的。
最好是加上explicit,需要转换时显示强制转换。可控的显式的流程才清晰明了~~