c++的函数

函数的区别

1、函数重载:

1、C++中的函数重名,我们把这项技术叫函数重载。

2、重载的函数,参数列表必须不同,即参数的个、类型不同。

3、调用函数时会根据实参的数据类型自动选择调用那个函数,如果与实参相符的函数没有定义,则可以对实参进行自动类型转换调用相关函数,如果实参进行自动类型转换后有多个选则会导致调用冲突。

#include <iostream>
using namespace std;
​
void func(long num)
{
    cout << "func long类型参数" << endl;
}
​
void func(short num)
{
    cout << "func short类型参数" << endl;
}
​
int main(int argc,const char* argv[])
{
    func(1234);
    return 0;
}
​

4、如果函数的参数是指针或引用,指针变量是否使用const修饰会影响函数重载。

void func(int* p)
{
    cout << "func int* p" << endl;
}
​
void func(const int* p)
{
    cout << "func const int* p" << endl;
}
​
int main(int argc,const char* argv[])
{
    int num1;
    func(&num1); // void func(int* p)
    const int num2;
    func(&num2); // void func(const int* p)
    return 0;
}
构成函数重载的条件:

1、同一个作用域

2、函数名相同

3、参数列表不同(参数的个数、类型,指针、引用是否加const)

函数重载的原理:

C++中的函数重载并不是真正的重名,而是在编译时编译器会把函数的参数列表信息追加到函数名的末尾,也就是在编译时函数名经历的换名的过程,在函数调用时,编译器会把实参的类型信息追加到函数名的末尾,这样就知道该调用哪个函数了。

// _Z4funcPi:
void func(int* p)
{
    cout << "func int* p" << endl;
}
​
// _Z4funcPKi:
void func(const int* p)
{
    cout << "func const int* p" << endl;
}
​
// _Z4funcii:
void func(int num,int num1)
{
    cout << "func const int int" << endl;
}
C++中如何使用C的库文件:
面临的问题:

1、把函数声明头文件导入后,默认情况下g++会按照C++的语法声明函数,会把C头文件中的函数声明进行换名。

2、g++在编译调用函数的语句时,会先尝试调用换名的函数,此时发现已经声明过,所以编译器生成的换名的函数调用指令,而C的库文件中的函数没有换名,所以就会调用失败,也就链接失败。

解决方法:

1、使用extern "C" 包含一下C函数声明,这个语句的功能就是告诉编译器按照C语言的处理方式编译函数声明,也就是不要对函数进行换名。

2、g++在编译调用函数的语句时,会先尝试调用换名的函数,此时会发现没有该版本的函数声明,然后再尝试调用未换名的函数,这样编译器生成就是未换名的函数调用指令,就能成功调用C的库文件中的函数。

注意:函数重载不是为实现通用代码,只为了提高代码的可读性(降低取名难度)。

练习:使用函数重载技术实现一个基本类型通用的冒泡排序函数。

signed char         
signed short        
signed int          
signed long        
   
unsigned char       
unsigned short     
unsigned int        
unsigned long       
    
单精度: float           
双精度: double          
​
字符串类型

2、默认形参

1、在声明函数时,可以给函数的形式参数设置一个默认值,当调用函数时,设置过默认值的参数位置可以不提供实参,会使用默认值。

#include <iostream>
using namespace std;
​
void func(int num1=1234,int num2)
{
    cout << num << endl;
}
​
int main(int argc,const char* argv[])
{
    func(123);
    return 0;
}

2、设置默认值的参数要连续且靠右,因为调用者提供的实参要优先提供给没有设置默认的参数使用。

// 错误写法
void func(int num1,int num2=1234,int num3=456)
{
    cout << num1 << " " << num2 << " " << num3 << endl;
}
​
int main(int argc,const char* argv[])
{
    func(1,2,3);
    return 0;
}

3、如果函数的声明和定义分开实现,则只能在声明函数时设置默认形参,定义函数时不能设置默认形参,因为没有意义。

void func(int num1,int num2,int num3=1234);
​
int main(int argc,const char* argv[])
{
    func(1,2);
    return 0;
}
​
void func(int num1,int num2,int num3)
{
    cout << num1 << " " << num2 << " " << num3 << endl;
}

函数设置默认形参可能会造成调用时的冲突,如果该函数进行重载,又对部分函数设置的默认形参,就可能导致调用函数时有多个备选方案,造成调用冲突。

void func(int num1,int num2)
{
    cout << num1 << " " << num2 << endl;
}
​
void func(int num1,int num2,int num3=1234)
{
    cout << num1 << " " << num2 << " " << num3 << endl;
}
​
int main(int argc,const char* argv[])
{
    func(1,2);
    return 0;
}
3、内联函数:

C++标准委员会设计一种特殊函数,函数在声明时在返回值类型的前面增加 inline 关键字,当调用该函数时,编译器不会生成跳转指令,而是函数的二进制指令直接拷贝到调用位置,这样执行该函数时,直接执行二进制指令,不需要跳转,也不需要返回,所以执行速度比普通函数快,就像宏函数,但过多使用会造成冗余,代码段变大。

注意:内联函数只是C++标准委员会设计方案,具体是否内联要看编译厂商是否实现了内联功能。

编译器优化:

gcc/g++ -On 设置编译器的优化级别

默认情况下是-O0,不进行内联,-O2以上才会进行内联。

与宏函数的相同点和不同点:
相同点:

没有跳转、返回过程,提高代码执行速度,都会造成过多使用会造成冗余,代码段变大。

不同点:

1、内联函数会检查参数的类型和个数,宏函数只会检查参数的个数而不会检查类型,内联函数比宏函数安全。

2、宏函数提供任何类型的参数都可以调用,但内联函数的实参只能使用部分类型,宏函数比内联函数的通用性强。

3、内联函数可以有返回值,而宏函数没有。

什么样的函数适合设置为内联函数:

与宏函数一样,请参考C语言的笔记。

注意:结构、联合、类的成员函数默认都设置为了内联函数,这种内联被称为隐式内联,使用inline修饰的函数被称为显式内联。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值