zoukankan      html  css  js  c++  java
  • 初步理解[函数重载]和[运算符重载]·转

    作者:黄兢成
    链接: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++中的解决方法,不一定最好的。

  • 相关阅读:
    bzoj2809 [Apio2012]dispatching
    bzoj2743[HEOI2012]采花
    bzoj3626[LNOI2014]LCA
    bzoj2038 [2009国家集训队]小Z的袜子(hose)——莫队
    bzoj2442[Usaco2011 Open]修剪草坪——单调队列优化
    bzoj1588[HNOI2002]营业额统计——双向链表
    洛谷1527(bzoj2738)矩阵乘法——二维树状数组+整体二分
    bzoj1503[NOI2004]郁闷的出纳员——Splay
    洛谷P2014——选课
    洛谷P1352——动规
  • 原文地址:https://www.cnblogs.com/n2meetu/p/6710392.html
Copyright © 2011-2022 走看看