链接:https://www.zhihu.com/question/23407045/answer/24543450
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
很多疑问都是想不通那东西具体用于什么地方。
比如我初学 C++ 时,早就知道指针实际就是某个变量的地址,就是不知道具体怎么用。这感觉就仿佛学数学,我知道某定理,也知道某定理的证明是对的,但我就是不知道这东西有什么用。直到学数据结构,接触到链表,才突然明白指针。
所以语法只是初步,更重要的是要想明白遇到什么问题了,才需要有那个语法。之后再进一步,去探究具体实现。
去想想
- 遇到什么问题?约束条件是什么?
- 在这约束条件下,那些人是怎么解决的?
- 怎么去评价那个解决方法?
- 现在那个约束条件存在不?假如不存在了,是不是有更好的?
重载函数
重载,英文为 overloading,大概就是很多个的意思。
举个例子,我需要个函数取 2 个 int 的最大值。函数接口应该是
(1) int max(int a, int b);
那更进一步,我取3个 int 的最大值呢,接口可以定义为
(2) int max(int a, int b, int c);
函数 (1) 和 (2)的名字是一样的,都叫 max,就只有参数的个数不同。这是函数重载。
那现在,我需要取两个float的最大值呢,接口也可以定义为
(3) float max(float a, float b);
对比 函数(1) 和 (3),名字也是一样的,参数个数也是一样的。不过参数的类型不同。这也是函数重载。
所以函数重载就是,名字相同,但参数个数不同或者参数类型不同。
够简单吧。
不过,我相信到这里还会似懂非懂的。那我们去设想一下,上面的例子,假如没有重载,也就是函数的名字不可以相同,那会怎么样?
第(1)个函数,还是叫max吧。那第(2)个函数,就不能叫max了。就叫max3吧,因为有3个参数。这样第(1)个函数还是叫max不好吧,就叫max2, 有两个参数,跟max3对应起来。那第(3)个函数怎办。因为是2个浮点。就叫max2f吧。f表示浮点。
那现在 max2, max3, max2f又不统一了。就叫 max2i, max3i, max2f, 吧。那到时 double, long, long long类型,各自有2个参数,或者3个参数。那就出现 max2i, max3i, max2f, max3f, max2l, max3l ......
同一个取最大值的概念。出现了多个不同的名字。似乎不好吧。可能你觉得上面的例子是我作的,真实中应该不至于这样吧。但实际上在 C 语言中,就发生这样的事情。
C 语言就没有函数重载的。下面都是 C 标准库中取绝对值的函数。
float fabsf(float); double fabs(double); long double fabsl(long double); int abs(int); long labs(long); long long llabs(long long);
有了重载和模板(模板这里不说),C++ 中就为 std::abs,只有一个名字。
另一个例子,就是 C 语言写的 OpenGL 接口,下面函数都是定义顶点。
glVertex4i
glVertex4s
glVertex2dv
glVertex2fv
glVertex2iv glVertex2sv glVertex3dv glVertex3fv glVertex3iv glVertex3sv glVertex4dv glVertex4fv glVertex4iv glVertex4sv
无重载,同一个概念,弄出这样多名字了。
运算符重载
运算符,就是 + - * / == != 那些符号。运算符重载,也就是可以重新定义那些运算符。
那有什么用呢?举个例子。
Point 表示点。两个点可以相加,相减,判断是否等于....
假如没有运算符重载。需要定义这样的函数。
Point point_add(const Point& a, const Point& b); Point point_sub(const Point& a, const Point& b);
使用起来,就是。
Point c = point_add(a, b); Point d = point_sub(c, a);
又加又减,会变成
Point d = point_add(a, point_sub(c, d));
而在 C++ 中重新定义运算符号,可以写出这样的代码
Point c = a + b; Point d = c - a; .... Point d = a + (c - d);
对比一下,运算符重载会更易读易写。
运算符重载可以算个语法糖,无这个东西还是可以写代码,不过没有写得那样漂亮自然。当做一件事情很麻烦的时候,通常就偷懒不去做了。
再举个我遇到的例子。最近用到个object-c 库 Masonry。object-c 没有运算符重载,这个库有些代码写起来是这样写的。不用管它的意思。就去感受一下。
make.top.equalTo(superview.top).with.offset(padding.top); make.left.equalTo(superview.left).with.offset(padding.left); make.bottom.equalTo(superview.bottom).with.offset(-padding.bottom); make.right.equalTo(superview.right).with.offset(-padding.right); ....... make.width.greaterThanOrEqualTo(@200); make.width.lessThanOrEqualTo(@400);
同样的含义,假如有了运算符重载。我相信可以写成这样。
make.top == superview.top + padding.top; make.left == superview.left + padding.left; make.bottom == superview.bottom - padding.bottom; make.right == superview.right - padding.right; ...... make.width >= @200; make.width <= @400;
看看代码的美感。功能虽然一样,但是否漂亮,会有根本的不同。
不过要注意。C++有些地方也会写得很丑的,比较多余的。同样问题,不同的语言会有不同的做法。C++中的解决方法,不一定最好的。