c++学习笔记(二、c++对c函数的扩展)

学习语言都是比较枯燥的,不过不学会语言知识,直接看代码确实不好。今天继续c++第二天

2.1 内联函数

c++的内联函数和c的一样,本来不想写的,不过当做一次复习吧。
特点:

  1. 内联函数声明时inline关键字必须和函数定义结合在一起
  2. 编译器直接将函数体插入到函数调用的地方
  3. 内联函数没有其他函数调用时的开销(压栈、跳转、返回)
  4. 内联函数是一种特殊的函数,具有普通函数的特征。(可以检查参数,返回值等)
  5. 内联函数由编译器,直接将编译后的函数体插入调用的地方,宏代码片段 由预处理器处理,进行简单的文本替换,没有任何编译过程。
  6. C++中内联编译的限制
    不能存在任何形式的循环语句。
    不能存在过多的条件判断语句。
    函数体不能过于庞大。
    不能对函数进行取址操作
    函数内联声明必须在调用语句之前
  7. 当函数体的执行开销远大于压栈,跳转和返回所用的开销时,那么内联将无意义。
    来自《黑马程序员C++课程》

2.2 函数默认参数和占位参数

c++中函数是支持默认参数的

int get_area(int len, int width, int height)
{
    return len * width * height;
}

int get_area2(int len = 10, int width = 20, int height = 30)
{
    return len * width * height;
}

int main(int argc, char **argv)
{
    cout << "hello c++ " << my_spaceA::my_spaceB::haha << endl;
    int area = 0;

    area = get_area(10, 20, 30);
    printf("area = %d\n", area);

    area = get_area2();
    printf("area = %d\n", area);
	area = get_area2(20, 30, 40);
    printf("area = %d\n", area);
    return 0;
}

函数的默认参数就是在函数的形参加个等号=什么,如果函数有默认值的时候,传参的时候可以不传参数的,如果我们传入了参数的话,函数就会用我们传入的参数,而不用默认值。

如果某个参数是默认参数,那么它后面的参数都要是默认参数,默认参数是从右到左的,因为填参数的时候是从左到右的,这样才不冲突。

这样是正确的:
int get_area2(int len, int width = 20, int height = 30);
int get_area2(int len, int width , int height = 30);

这样就是错误的:
int get_area2(int len = 24, int width , int height);

占位参数:
占位参数只有参数类型的声明,没有参数名的声明
一般情况下,函数是无法使用占位参数的

int get_area(int len, int width, int height, int)
{
    return len * width * height;
}
//最后一个参数int  就是占位参数

给函数传参的时候,也需要传4个参数:
get_area(10, 20, 30, 40)
感觉有点难受,传入40也没啥用,体验一下默认参数+占位参数

int get_area(int len, int width, int height, int = 0)
{
    return len * width * height;
}

这样传参就是3个参数和4个参数都可以的,具体用法,有待以后学习。

2.3 函数重载

C++ 不允许变量重名,但是允许多个函数取相同的名字,只要参数表不同即可,这叫作函数的重载(读“虫载”,不读“众载”,其英文是 overload)。重载就是装载多种东西的意思,即同一个事物能完成不同功能。

2.3.1 重载的规则

  1. 函数名相同
  2. 参数个数不同,参数的类型不同,参数顺序不同,均可构成重载
  3. 返回值类型不同不可以构成重载
    例子:
    在这里插入图片描述

2.3.2 调用准则

1.严格匹配,找到则调用
2.通过隐式转换寻求一个匹配,找到则调用。
3.函数重载的时候,不要用默认参数,使用不当会引起冲突

int get_area(int len, int width, int height)
{
    return len * width * height;
}

还是上面的函数,我调用的时候:

area = get_area(10, 20, 30);
printf("area = %d\n", area);

 area = get_area('a', 20, 30);
 printf("area = %d\n", area);

这两个都可以匹配的上

2.3.3 重载底层实现

c++利用了name mangling(倾轧)技术,来改变函数名,区分参数不同的同名函数。
实现原理用vcifld表示void char int float long double及其引用。

void func(char a)  //func_c(char a)
void func(char a, int b, double c) //func_cid(char a, int b, double c)

我们用的时候可以写函数名一样的重载,但是底层还是自己转换成不同名字的,我觉得c语言也可以利用这种命名方式。

2.4 函数重载和函数指针

既然函数可以重载,函数指针在赋值的时候会不会有问题?
显然是不会的,实际上在给函数指针赋值的时候,是会发生函数重载匹配的,如果能匹配上指针,这个指针的地址就固定了,不能在重载其他函数了。所以在调用的时候,调用的函数也固定了。

int get_area(int len, int width, int height)
{
    printf("int int int\n");
    return len * width * height;
}

int get_area(int len, int width, int height, int aa)
{
    printf("char int int\n");
    return (*len) * width * height;
}

main函数:

int main(int argc, char **argv)
    {
        cout << "hello c++ " << my_spaceA::my_spaceB::haha << endl;
        int area = 0;

        int (*areap)(int, int, int) = get_area;
        areap(10, 20, 30);    //这个是ok的
        areap(10, 20, 30, 40);   //这个是编译不过的
        return 0;
    }
发布了32 篇原创文章 · 获赞 26 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/C1033177205/article/details/104073446