Unit02: 重载与缺省参数 、 内联与动态内存分配 、 引用 、 显式类型转换 、 类和对象

八、 c++ 的函数  

1. 函数重载
  eg: 图形库中画图函数
  c: 
    void drawCircle(int x, int y, int r){}
    void drawRect(int x, int y, int w, int h){}
    ...
  c++:
    void draw(int x, int y, int r){}
    void draw(int x, int y, int w, int h){}
    ...
  1) 函数重载的定义
    在相同作用域中,定义同名的函数, 但是它们的参数有所区别,这样的函数构成重载关系.
    注: 重载与函数返回类型无关,与参数名也无关.

  2) 函数重载的匹配
    调用重载关系的函数时,编译器将根据实参与行参匹配度,自动选择最优的重载版本.
    当前编译器(g++ 4.4.7)的一般匹配规则:
    完全匹配 > 常量转换 > 升级转换 > 降级转换 > 省略号匹配

  3) 重载实现原理
    c++ 编译器是通过对函数进行换名, 将参数表的类型信息整合到新的名字中,实现解决函数重载与名字冲突的矛盾.
    思考题: extern "C" 声明的作用?

2.  c++ 函数的缺省参数
    1) 可以为函数的部分或全部行参指定缺省值,调用该函数时,如果不给实参,就取缺省值作为相应的行参的值.
    eg:
    void func(int a, int flags = 缺省值){}
    int main(void){
        func(10);
        func(10, 20);
    }

    2) 缺省值必须靠右,如果一个参数带有缺省值,那么这个参数的右侧的所有行参都必须带有缺省值:
    eg:
    void func(int a = 100, int b = 200, int c){} // Error
    void func(int a, int b = 200, int c){} // Error
    void func(int a, int b, int c = 300){} // Ok
    void func(int a, int b = 200, int c = 300){} // Ok

    3) 如果函数的定义和声明分开,缺省参数应该写到函数的声明部分,而定义部分不写,但是最好的注释,提高代码的可读性。
    void func(int a = 100) // 函数的声明
    void func(int a /*= 100*/){} // 函数的定义

3.  c++ 函数的哑元参数
    1) 定义: 只有类型没有变量名的行参称为哑元
        void func(int /* 哑元参数 */){
            // code
        }
        int main(void){
            func(100);
        }

    2) 为了兼容旧代码
        eg:
        算法库: 
        void math_func(int a, int b){
            // code
        }
        使用者:
        int main(void){
            math_func(10,20);
            math_func(20,50);
            math_func(30,50);
            // ...
        }
        ------------------------
        升级算法库:
        void math_func(int a, 哑元){
            // ...
        }
        使用者:
        int main(void){
            math_func(10,20);
            math_func(20, 50);
            math_func(30, 50);
            // ...
        }
    3) 运算符重载, 区分前后 ++/-- 

4.  内联函数 inline
    // 思考题: inline 关键字的作用

    八、 4 思考题答案
    使用 inline 关键字修饰的函数, 表示这个函数是内联函数, 编译器会尝试做内联优化,避免函数调用的开销.
        1) 多次调用的小而简单的函数适合内联
        2) 调用次数极少或者大而复杂的函数不适合内联
        3) 递归函数不能内联
        4) 内联只是一种建议而不是一种强制要求, 能否内联主要取决于编译器,有些函数不加 inline 关键字也会以内联的方式展开,有些函数即便加了 inline 关键字也不会处理为内联。

    九、 c++ 的引用 (reference)
        1.  定义引用就是给某个变量起别名,对引用的操作与对变量的操作完全相同。
        int a = 10;
        int &b = a; // 定义引用 b, b 就是 a 的别名
        b++;
        cout << a << endl; // 11

        2.  常引用
            1) 定义引用的时候加 const 修饰, 即为常引用, 不能通过常引用修改引用的目标
            eg:
            int a = 100;
            const int& b = a; // b 就是 a 的常引用
            b = 20; // Error

            2) 普通的引用只能引用左值(变量), 常引用也叫万能引用,既可以引用左值也可以引用右值。
            eg:
            int &r = 100; // Error
            const int& r = 100 // Ok

        3.  关于左值和右值的概念
            1) 左值: 可以放在赋值运算符的左边,可以被修改, 可以被取地址.
            int i;
            i = 100;
            ++i;
            &i;
            常见左值:
            - 变量
            - 前++/-- 表达式的值、赋值表达式的值
            eg:

            int number = 1;
            cout << (++number) << endl; // 2
            cout << (number) << endl; // 2
            ++number = 10; // Ok
            ++++++number;

            eg:
            int a = 10;
            int b = 20;
            (a = b) = 30;
            cout << a << endl; // 30
            cout << b << endl; // 20

            2) 右值: 只能放在赋值运算符右边,不可以被修改, 不可以被取地址.
            常见右值:
            - 字面值
                10 = i; // Error
                ++10; // Error
                &10; // Error
            - 大部分表达式的值
            eg:
            int number = 1;
            cout << (number++) << endl; // 1
            cout << (number) << endl; // 2
            number++ = 20; // Error
            number++++; // Error
            eg:
            int a = 3;
            int b = 5;
            (a + b) = 10; // Error

            - 函数返回值
              int func(void){
                int a = 100;
                return a; // 将 a 保存到一个临时变量中: temp = a
              }
              int main(void){
                int res = func(); // int res = temp
                foo() = 200; // Error
                ++foo(); // Error
              }

        4. 引用型的参数
            1) 可以将引用用于函数的参数, 可以直接修改实参变量的值, 同时可以减少函数调用的开销:
            eg:
            void func(int& a = x){
                a++;
                cout << a << endl; // 2
            }
            int main(void){
                int x = 1;
                func(x);
                cout << x << endl; // 2
                return 0;
            }

            2) 引用参数有可能意外修改实参变量的值,如果不希望修改实参本身,可以将行参定义为常引用, 在提高传参效率的同时还可以接收常量型的实参。

            思考题:
            1.  使用引用参数完成两个字符串(char*)的交换
            int main(void){
                const char* s1 = "hello";
                const char* s2 = "world";
                swap4(s1, s2);
                cout << s1 << endl; // world
                cout << s2 << endl; // hello
            }

            2. 总结引用和指针的区别和联系

    八、 1 (3)思考题答案
    思考题答案: 函数声明前加入 extern "C"要求 c++ 编译器不对函数做换名,编译 c 程序调用该函数.
    注: 这样的函数无法重载
    eg:
    extern "C" void func(void){// code}
    extern "C"{
        void func1(){// code}
        void func2(){// code}
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

胡德咏

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值