目录
设计出来的一个类所产生出来的对象,可能会像两种东西的,一种是像一个指针(智能指针),另一种是像一个函数(仿函数)。
pointer-like classes
那么为什么要把一个类所设计出来的对象,要让它像一个指针呢?因为我们希望这个对象可以做出比指针更多的事情。所以,这种对象我们一般称它为智能指针(类似手机的概念,智能手机比普通手机更聪明,所以智能指针也是比普通指针更聪明的!)。
应该说明的是,智能指针其实是一个对象,但智能指针里面肯定是包含着一个真正的指针的!但也同时,指针所能做的事情,智能指针也是要都能做到的!
下面是标准库中的一段代码,里面有指针变量px与pn,那么什么样的操作符会用到指针上面呢?以当前示例来讲,那就是一个“*”符号,另一个是“->”符号,智能指针是可以代表一般指针的,而一般指针不止用到这两个符号上,还有其他的,但在此我们就讨论这两个。
智能指针的构造
下面看看类中的两个操作符重载要做什么事情,由于智能指针(是个对象)肯定是包含真正的指针的,换句话说,要接纳真正的指针,故"shared_ptr(T* p) : px(p) { }"就是起这个作用的,在外界,
shared_ptr<Foo> sp(new Foo);
"shared_ptr<Foo> sp(new Foo);"就是调用的这个构造函数,上图中的中上部分的图形表示的就是这个。
智能指针符号"*"的重载
完成这个动作之后,就可以用这个所创建的对象sp,充当一个指针来用了!那么下面来看看在外界这个智能指针怎么使用:
Foof f(*sp)
这个就对应的类定义里面的"*"的重载,那么"*"本身的作用就是取地址(解参考),就是提取变量的地址,为了让这个对象也起到指针的效果,就需要重新定义"*"这个操作符,就需要重新定义智能指针对这种情况的呼应,把真实的地址给返回回去。所以,对于智能指针的这种星号写法,无一例外都是这么写的!
智能指针符号"->"的重载
sp->method();
这个就对应的类定义里面的"->"的重载,"->"的意思其实很直关,等同于调用sp对象下的method的这个函数,但毕竟sp是个对象不是指针,那么同理,这个也和星号一样,为了让智能指针达到和普通指针一样的效果,需要重载相关的运算符。让"sp->method();"等同于"px->method()"(箭头符号有个特殊的效果,就是作用之后,还可以继续作用下去)。同理,对于智能指针的这种箭头符号写法,无一例外都是这么写的!
那么问题来了,根据类中的定义,箭头符号重载后返回的是"px",那为啥还能跟method函数扯上关系呢?这是因为箭头符号有特殊效果,可以在作用之后继续作用,即"sp->method();"运行后,会继续执行"px->method()",因为箭头符号有继续作用的效果,就直接转换为了用返回的px来指向method()函数了!也就起到了通过指针来调用method()函数了!
迭代器作为另外一种指针的操作符重载(示例)
如果是新手,强烈建议去使用库,如果使用库的话,肯定会遇到容器,那么使用容器的话肯定会遇到迭代器,好,既然提到了迭代器,那么我们就来好好说说(好牵强—— ——||),迭代器就是代表容器这样一个元素去指向另外一个元素,因此,迭代器也像一个指针,甚至都可以当成一个智能指针,只不过跟之前说的长相,略有不同,比之前要更复杂,重载的操作符也更多,如下,
那么下面就开始探究一下,下面是一个双向链表,每个data上面带有两个指针,链表的迭代器在图形撒谎给你显示就是node:
上图的右边是用法,左侧是定义和示意图。当用的时候按一个指针的方式去用的时候,内部需要去按照指针的方式去响应,如果做不到,就重载操作符,起到按指针的方式去响应的效果。
function-like classes
函数调用操作符的重载
设计一个类,让其行为像一个函数,这就是所谓的仿函数。既然是要像一个函数,那么就需要先知道函数是长什么样子的,函数有函数名称,要有一个小括号给作用上去,这个小括号有专门的名称,叫函数调用操作符,所以,任何东西只要能接受小括号这个操作符,我们就可以叫这个东西叫做一个函数,或者一个像函数的东西(function like)。
那么还是在标准库中的这三个模板类函数来做例子,看下:
首先,identity意思是证明为同一个东西,运行逻辑很简单,你给它传啥,它就返回啥;select1st意思是使用pair(一对儿)才行,同理select2nd,是跟前面那个select1st成对儿的。
仿函数都会继承一些奇特的基类
那么做下总结,如果看见一个类中有类似这样的结构,即出现了"operator() ..."去重载小括号,那这个类所创建的对象就是个函数对象,也可以称为仿函数,那么上图中的每个函数中,有个灰色的部分,那灰色的部分是什么内容呢?这个部分是继承,因为仿函数一般都会继承一些奇特的base classes,下面就是在标准库中,仿函数所使用到的奇特的base classes.
总结一下,标准库里面有很多仿函数,它们的本质是一些重载了小括号的类, 这些仿函数都有继承一些奇特的父类,这些父类的大小是0,奇特就奇特在,这些父类没有具体的内容,只有一些typedef,具体的可以去详解c++的标准库中探查。