C++ 函数进阶

目录

缺省参数

缺省参数的分类

全缺省参数

半缺省参数

缺省参数应用

占位参数

函数重载

函数重载注意事项

C++支持函数重载的原理


缺省参数

缺省参数是声明或定义函数时为函数的参数指定一个缺省值。

在调用该函数时,如果没有指定实参则采用该形参的缺省值,否则使用指定的实参。

#include <iostream>
using namespace std;
 
void F(int a = 0)
{
	cout << "a = " << a << endl;
}
 
int main()
{
	F();//未指定实参,使用参数的默认值
 
	F(10);//传参时,使用指定的实参
 
	return 0;
}

缺省参数的分类

全缺省参数

void F(int a = 10, int b = 20, int c = 30)
{
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	cout << "c = " << c << endl;
	cout << endl;
}
 
int main()
{
	F(100);
	F(100, 200);
	F(100, 200,300);
	
	//传参时,必须从左往右依次给
	//错误示例:
	//F(100, ,300);
	return 0;
}

半缺省参数

void F(int a , int b , int c = 30)
{
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	cout << "c = " << c << endl;
	cout << endl;
}
 
int main()
{
	F(100,200);
	F(100, 200, 300);
 
	return 0;
}

注意:

1. 半缺省参数必须从右往左依次来给出,不能间隔着给;

//错误示例
void F(int a=10, int b, int c = 30)
{
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	cout << "c = " << c << endl;
	cout << endl;
}

2. 缺省参数不能在函数声明和定义中同时出现;

//错误示例
//test.cpp中定义
 
F(int a = 10);
 
//test.h中声明
 
F(int a = 20);
//编译器会报错

3. 缺省值必须是常量或者全局变量;

4. C语言不支持(编译器不支持);

缺省参数应用

在之前数据结构的学习中,我们经常用到某个函数给来实现对某种数据结构的初始化(以栈为例);

struct Stack
{
	int* a;
	int top;
	int capacity;
};
 
void StackInit(struct Stack* ps)
{
	int capacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
	ps->a = (int*)malloc(sizeof(int) * capacity);
 
	if (ps->a == NULL)
	{
		perror("malloc fail");
		return;
	}
 
	//...
}

这样的写法有一个缺点,不管我们需要多大的空间,每次调用初始化函数时第一次都只能开辟4的空间,看着很呆板。

但是运用缺省参数改进后:

void StackInit(struct Stack* ps, int defaultcapacity=4)
{
 
	ps->a = (int*)malloc(sizeof(int) * defaultcapacity);
 
	if (ps->a == NULL)
	{
		perror("malloc fail");
		return;
	}
 
	//...
}

当我们想指定开辟多大空间时只需要多传一个参数就可以了,否则默认为4。

当然除了这样的使用场景,缺省参数可以运用于很多很多场景,使得代码灵活性更高!

占位参数

C++中函数的形参列表里可以有占位参数,用来做占位,调用函数时必须填补该位置

语法: 返回值类型 函数名 (数据类型){}

//函数占位参数 ,占位参数也可以有默认参数
void func(int a, int) {
	cout << "this is func" << endl;
}

int main() {

	func(10,10); //占位参数必须填补

	system("pause");

	return 0;
}

函数重载

**作用:**函数名可以相同,提高复用性

函数重载满足条件:

  • 同一个作用域下

  • 函数名称相同

  • 函数参数类型不同 或者 个数不同 或者 顺序不同

注意: 函数的返回值不可以作为函数重载的条件

示例:

//函数重载需要函数都在同一个作用域下
void func()
{
	cout << "func 的调用!" << endl;
}
void func(int a)
{
	cout << "func (int a) 的调用!" << endl;
}
void func(double a)
{
	cout << "func (double a)的调用!" << endl;
}
void func(int a ,double b)
{
	cout << "func (int a ,double b) 的调用!" << endl;
}
void func(double a ,int b)
{
	cout << "func (double a ,int b)的调用!" << endl;
}

//函数返回值不可以作为函数重载条件
//int func(double a, int b)
//{
//	cout << "func (double a ,int b)的调用!" << endl;
//}


int main() {

	func();
	func(10);
	func(3.14);
	func(10,3.14);
	func(3.14 , 10);
	
	system("pause");

	return 0;
}

函数重载注意事项

  • 引用作为重载条件

  • 函数重载碰到函数默认参数

    //函数重载注意事项
    //1、引用作为重载条件

    void func(int &a)
    {
    cout << "func (int &a) 调用 " << endl;
    }

    void func(const int &a)
    {
    cout << "func (const int &a) 调用 " << endl;
    }

    //2、函数重载碰到函数默认参数

    void func2(int a, int b = 10)
    {
    cout << "func2(int a, int b = 10) 调用" << endl;
    }

    void func2(int a)
    {
    cout << "func2(int a) 调用" << endl;
    }

    int main() {

      int a = 10;
      func(a); //调用无const
      func(10);//调用有const
    
    
      //func2(10); //碰到默认参数产生歧义,需要避免
    
      system("pause");
    
      return 0;
    

    }

C++支持函数重载的原理

我们用函数重载定义函数Add,在我们眼中,两个函数名字相同,参数不同,调用函数时,我们知道应该调用哪个,那么编译器在链接阶段,如何知道去哪寻找对应的函数栈帧呢?

int Add(int a, int b)
{
	return a + b;
}
 
double Add(double a, double b)
{
	return a + b;
}
 
int main()
{
	Add(10, 20);
	Add(2.2, 3.3);
 
	return 0;
}

其实编译器在编译与汇编阶段,会对函数名做修饰。不同的编译器对函数名的修饰也不同,为了方便观察,这里以Linux环境下的g++编译器为例。输入指令查看可执行程序反汇编的代码:

g++ Test.cpp -o Testcpp
objdump -S Testcpp

以下是Linux下g++修饰的汇编代码:

为了作对比,我们再看看没有函数重载的C语言是否会对函数名做修饰:

gcc Test.c -o Testc
objdump -S Testc

C代码:

#include<stdio.h>
 
int Add_int(int a, int b)
{
	return a + b;
}
 
double Add_double(double a, double b)
{
	return a + b;
}
 
int main()
{
	Add_int(10, 20);
	Add_double(2.2, 3.3);
 
	return 0;
}

汇编代码:

通过这里就理解了C语言没办法支持重载,因为同名函数没办法区分。而C++是通过函数修饰规则来区分,只要参数不同,修饰出来的名字就不一样,就支持了重载。

最后补充,如果两个函数函数名和参数是一样的,返回值不同是不构成重载的,因为调用时编译器没办法区分。

相关推荐
测试盐5 分钟前
c++编译过程初识
开发语言·c++
single5942 小时前
【c++笔试强训】(第四十五篇)
java·开发语言·数据结构·c++·算法
yuyanjingtao3 小时前
CCF-GESP 等级考试 2023年9月认证C++五级真题解析
c++·青少年编程·gesp·csp-j/s·编程等级考试
魔法工坊4 小时前
只谈C++11新特性 - 删除函数
java·开发语言·c++
海螺姑娘的小魏4 小时前
Effective C++ 条款 26:尽可能延后变量定义式的出现时间
开发语言·c++
w(゚Д゚)w吓洗宝宝了4 小时前
C++ 环境搭建 - 安装编译器、IDE选择
开发语言·c++·ide
王老师青少年编程5 小时前
gesp(二级)(16)洛谷:B4037:[GESP202409 二级] 小杨的 N 字矩阵
数据结构·c++·算法·gesp·csp·信奥赛
机器视觉知识推荐、就业指导6 小时前
C++设计模式:解释器模式(简单的数学表达式解析器)
c++·设计模式·解释器模式
海螺姑娘的小魏6 小时前
Effective C++ 条款 16:成对使用 `new` 和 `delete` 时要采取相同形式
开发语言·c++
点云SLAM7 小时前
C++创建文件夹和文件夹下相关操作
开发语言·c++·算法