C++ (第二天上午---函数重载和缺省参数和占位参数)

一、函数重载

1、问题的引入
在实际开发中,有时候我们需要实现几个功能类似的函数,只是有些细节不同。例如希望交换两个变量的值,这两个变量有多种类型,可以是 int、float、char、bool 等,我们需要通过参数把变量的地址传入函数内部。在C语言中,程序员往往需要分别设计出三个不同名的函数,其函数原型与下面类似:

void swap1(int *a, int *b);      //交换 int 变量的值
void swap2(float *a, float *b);  //交换 float 变量的值
void swap3(char *a, char *b);    //交换 char 变量的值
void swap4(bool *a, bool *b);    //交换 bool 变量的值

那么在C++中,有没有一种方法,允许多个函数拥有相同的名字,只要它们的参数列表不同就可以呢。
答案:使用函数重载。
2、概念
用相同的函数名定义多个不同的功能称为函数重载。重载的函数根据参数的个数和类型进行区分,但不能单独根据返回类型进行区分。
3、例子

void swap(int *a,int *b)
{
    *a = *a + *b;
    *b = *a - *b;
    *a = *a - *b;
}
void swap(float *a,float *b)
{
    *a = *a + *b;
    *b = *a - *b;
    *a = *a - *b;
}
void swap(char *a,char *b)
{
    *a = *a + *b;
    *b = *a - *b;
    *a = *a - *b;
}
void swap(bool *a,bool *b)
{
    *a = *a + *b;
    *b = *a - *b;
    *a = *a - *b;
}

在函数调用的时候会根据不同的参数列表选择调用对应的函数
4、函数重载的规则

  • 函数名称必须相同
  • 参数列表必须不同(个数不同、类型不同、参数排列顺序不同等)
  • 函数的返回类型可以相同也可以不相同。
  • 仅仅返回类型不同不足以成为函数的重载
    5、函数重载的作用
  • 解决函数名字资源问题
  • 函数调用的时候很方便,自动根据不同的参数调用不同函数(静态多态-编译时候多态)
    6、注意
    在c++中编译器会检查函数名称和参数列表, 在c语言中编译器只检查函数名称
    7、函数重载原理
    在这里插入图片描述
    总结:返回值不一样不能实现函数重载
    const参数能实现函数重载

二、函数默认参数(缺省实参)和占位参数

1、概念
在声明函数的时候可以赋予函数参数默认值。所谓默认值就是在调用时,可以不写某些参数的值,编译器会自动把默认值传递给调用语句中。
2、特点

  • 如果函数的声明和定义是分开的,必须在声明的时候设置默认值,不可以在定义的时候设置默认值;
  • 不能将实际值传递给引用类型的参数。可以将变量作引用类型参数的默认值,这时变量必须是已经声明且是全局变量
#include<iostream>

using namespace std;

int g_val = 10;

//默认值是在函数声明的时候进行设置
int func(int a=10);
//不能将实际值传递给引用类型的参数。可以将变量作引用类型参数的默认值,这时变量必须是已经声明且是全局变量 
//int rfunc(int &a=10); --除非 const int &a=10
int rfunc(int &a=g_val);

int main()
{
    func();
    return 0;
}
//如果函数的定义和声明是分开的,那么函数定义的时候不能设置默认值,而是在声明的时候进行设置
int func(int a)
{
    cout<<"a:"<<a<<endl;
}
int rfunc(int &a)
{
    cout<<"a:"<<a<<endl;
}
  • 若给某一参数设置了默认值,那么在参数表中其后所有的参数都必须也设置默认值
如果多参数默认,必须满足从右往左连续默认
void fun(int a, int b=9, int c=1); 允许
void fun(int a=1, int b, int c=2); 不允许

3、占位参数
占位参数:跟默认参数不同,在函数定义时,形参只写类型,不写形参变量名
语法:

返回值类型  函数名(type ) //type --- int char
{
    
}
占位参数的使用场景比较少,只在运算符重载中可以应用
void test(int) //占位参数
{

}
void test1(char) //占位参数
{

}
int main()
{
    int b = 10;
    test(b); //带占位参数的函数调用时,要传入对应类型的参数值
    return
}

练习5:使用链表设计一个录入学生信息的函数(参数为学生信息)(输入信息有个学号,姓名,年龄,班级 参数顺序自定),结合函数重载和默认参数的特点,设计的时候使后期使用更方便

#include <iostream>
#include <cstring>


/* 练习2:设计一个录入学生信息的函数(参数就是学生信息)
(输入的时候有姓名、年龄、班级...),结合函数重载和默认参数的特点
设计出来的程序使用的时候 更加方便 */

using namespace std;

enum MODE
{
    ADD, //增加
    SHOW,    //显示
    EXIT    //退出
};

struct student{
    char name[256];
    int age;
    char classes[256];//班级
};

//单向非循环链表
typedef struct node{
    struct student info;//数据域

    struct node *next;//指针域
}Node_t;

//链表的头结点
typedef struct list{
    Node_t *head;//数据的首结点
    Node_t *tail;//数据的尾结点

    int nodeNumber;//链表中结点的个数
}List_t;


List_t *create_list()
{
    //1、申请一个头结点的内存空间
    List_t *list = new List_t;

    list->head = list->tail = NULL;
    list->nodeNumber = 0;

    return list;
}

void insert_nodeToList_tail(List_t *list,const char *name,const int age=21,const char *classes="gz2166")
{
    if(list==NULL)
        return ;
    //1、新建数据结点
    Node_t *newNode = new Node_t;

    //2、初始化
    strcpy(newNode->info.name,name);
    newNode->info.age = age;
    strcpy(newNode->info.classes,classes);

    newNode->next = NULL;

    //3、将新建的结点插入到链表中
    if(list->head == NULL) //从无到有
    {
         list->head = newNode;
         list->tail = newNode;
    }
    else{ //从少到多  ---尾插法
        //当前尾结点的next指向新结点
        list->tail->next = newNode;
        //更新尾结点
        list->tail = newNode;
    }

     list->nodeNumber++;

}

void print_allToList(List_t *list)
{
    Node_t *p = list->head;

    cout<<"姓名\t\t"<<"年龄\t"<<"班级\t"<<endl;

    while(p)
    {
         cout<<p->info.name<<"\t\t"<<p->info.age<<"\t"<<p->info.classes<<"\t\t"<<endl;

        p = p->next;
    }
}

int main()
{
    List_t *list = create_list();

    insert_nodeToList_tail(list,"zhang3",22);
    insert_nodeToList_tail(list,"li4");
    insert_nodeToList_tail(list,"laowang",23,"gz2169");

    print_allToList(list);
    return 0;
}

四、函数重载与函数默认参数
思考:假如一个程序中有如下两个函数

void test()
{
}
void test(int x=10)
{
}
调用:
test(11);//调用 的是:void test(int x=10)
test();//调用的是???歧义

答案:有歧义,解决方法:可以定义命名空间

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值