c++入门之缺省参数和函数重载

1.雀省参数的概念

缺省参数是==声明或定义函数==时为函数的参数指定一个缺省值。在调用该函数时,如果==没有指定实参==则采用==该形参的缺省值==,否则使用指定的实参。

#include <iostream>
using namespace std;

void fun(int x = 10)
{
    cout << x <<endl;
}
int main()
{
    int a = 100;
    fun();//没有传入参数的时候就是用给定的缺省值
    fun(a);//传入参数的事就就是用给定的参数!
}

image-20220918115411697.png

1.1缺省值的分类

缺省值分为全缺省和半缺省

#include <iostream>
using namespace std;

int func(int a = 10,int b = 100,int c = 1000)//这就是全缺省
{
    return a+b+c;
}
int func1(int a,int b = 100,int c =1000)//这就是半缺省
{
    return a+b+c;
}
int main()
{
    cout << func() << endl;
    cout << func1(100) << endl;
}

image-20220918120131486.png

1.2缺省值的使用注意

  • 缺省值必须从右往左连续缺省!
#include <iostream>
using namespace std;

int func(int a = 10,int b = 100,int c)
{
    return a+b+c;
}

int func1(int a = 10,int b,int c = 1000)
{
    return a+b+c;
}

int func2(int a,int b = 100,int c)
{
    return a+b+c;
}

//这样的设置缺省值是会报错的!

image-20220918120712564.png

  • 缺省值不可以同时在声明和定义中同时存在!
  • //a.h(在头文件a中)
    int func(int a = 10);
    
    //a.cpp (在源文件a中)
    int func(int a = 10)
    {
        return a;
    }
    

    这是为了防止在声明和定义中出现完全不同的缺省值导致二义性!

  • 缺省值必须是常量或在全局变量!
  • 缺省值不兼容c语言!

1.3缺省值的应用

缺省值可以让我们在已知必要的前提条件下更好的节省程序的性能!

using namespace std;
namespace bit
{
    struct stack
    {
        int* a;
        int capacity;
        int top;
    };

    void StackIint(stack* p)
    {
        int capacity = 4;
        assert(p);
        int* temp = (int*)malloc(sizeof(int) * capacity);
        if (temp)
        {
            perror("malloc fail");
            return;
        }
        p->capacity = capacity;
        p->top = 0;
        p->a = temp;
    }//这是我们一开始使用的栈的初始化,这个方式有一个缺点,加入我们已经知道了需要的空间的大小!我们仍需要在插入的时候使用realloc开辟新的空间!浪费不必要的性能!
    void StackIint_2(stack* p ,int defaultCP = 4)
    {
        assert(p);
        int* temp = (int*)malloc(sizeof(int) * defaultCP);
        if (temp)
        {
            perror("malloc fail");
            return;
        }
        p->capacity = defaultCP;
        p->top = 0;
        p->a = temp;
    }//使用了缺省值后,我们就可以在已知需要开辟多少空间的条件下,一次性开辟出足够的空间,使程序足够的灵活,而且保持程序的使用方式仍与上面的那种一样!

}


int main()
{
    bit::stack a;
    bit::StackIint_2(&a);//不知道该使用多少内存

    bit::stack b;
    bit::StackIint_2(&b, 100);//知道使用多少内存
    return 0;
}

2.函数重载

函数重载:是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这 些同名函数的形参列表**(参数个数 或 类型 或 类型顺序)不同,常用来处理实现功能类似数据类型 不同的问题**。

int add(int x, int y)
{
	return x + y;
}
int add(double x, double y)
{
	return x + y;
}

int main()
{
	cout << add(1, 2) << endl;
	cout << add(10.9, 8.6) << endl;
}

image-20220918141119641.png

==利用函数重载的特性我们就可以制作出例如能兼容多种的类型的swap函数==,像是我们c++中经常使用的cout和cin函数,它自动识别类型的本质就是重载!

2.1函数重载的二义性!

void test()
{
    cout << "hahah" <<endl;
}
void test(int a =1 ,int b = 10)
{
    cout << a <<endl;
    cout << b <<endl;
}
int main()
{
    test(1);
    test(1,2);
    
    test();//这行代码会报错!因为系统无法辨别究竟要调用那个函数!
    //函数重载+缺省参数!
    return 0;
}

2.2 编译重载的原理

在预编译的过程中有一个符号表!符号表存储着函数名和地址!

对于c语言,它会==粗糙地不加修饰==把所有参数名和地址统统放进去!

而c++会对根据函数image-20220918142036829.png的参数的不同类型,不同数量,类型顺序对函数名进行修饰!

在linux的g++中以c语言编译器下编译后的结果

image-20221020170608821.png

可以看出函数名是完全没有变化的!

在linux的g++中以c++器下编译后的结果

image-20220918143707704.png

在linux下,采用g++编译完成后,==函数名字的修饰发生改变==,编译器将函数==参数类型信息==添加到修改后的名字中。