我的C++学习历程(三)

内联函数

在C++中内联函数是为了解决使用宏出现的一些问题,而引入的

宏函数的缺陷:代码中列举了两种情况

#include <iostream>
#include <string>
using namespace std;

//内联函数

//定义一个加法   使用宏的时候需要加上对应的括号,
//要不在预处理阶段会出现,计算优先级的问题
#define  MyAdd(x,y)  ((x)+(y))

void test01()
{
    int ret = MyAdd(10,20)*20;   //预期结果600   (10+20)*30 = 410
    cout<<"ret = " << ret <<endl;
}

//大小比较
#define MyCompore(a,b)  ((a) < (b) ? (a) : (b))

void test02()
{
    int a = 10;
    int b = 20;
    int ret = MyCompore(a,b);     //(10) < (20) ? (10) : (20)
    cout<<"ret = " << ret <<endl;
    int ret1 = MyCompore(++a,b);     //(++10) < (20) ? (++10) : (20)
    cout<<"ret1 = " << ret1 <<endl;  //按照正常逻辑返回的应该是11
}

//宏函数也没有作用域

int main()
{
    //test01();
    test02();
    return 0;
}

为了解决这样的缺陷就引入了内联函数

内联函数的注意事项:

1.内联函数需要加inline关键字

2.类内部的成员函数前面默认会加inline关键字

3.内联函数和编译器

在某些情况下编译器不会把函数转化为内联函数
内联函数不能存在任何形式的的循环语句(开销比较大)
不能存在过多的条件判断语句
函数体不能过于庞大
不能对函数进行取址操作(最后函数体会被替换,就没有函数的地址了)

note:这个在撸代码的时候经常可以看见.h文件中,有的函数前面会加上这个关键字

函数的默认参数以及占位

在C语言中没有默认参数和占位参数

1.参数可以有默认值

函数参数u注意事项,如果一个位置有默认参数,如果一个位置有了默认参数,那么从这个位置从左往右都必须有默认参数

2.函数的声明和实现只能有一个有默认值(二义性)

3.函数有占位符(占位符也可以有默认值),调用的时候必须要提供这个参数

#include <iostream>
#include <string>
using namespace std;

//1.函数的默认参数   参数后面 = ...
//函数参数u注意事项,如果一个位置有默认参数,如果一个位置有了默认参数
//那么从这个位置从左往右都必须有默认参数
//传入参数,如果有参数,就用参数的值,没有参数就用默认值
void func(int a ,int b = 10, int c = 20)
{
    cout <<"a + b + c= " <<a + b + c<< endl;
}


void test01()
{
    func(1,2);
}

//2.如果函数声明里面有了默认参数,那么函数实现必须没有
//函数声明和实现里,只能有一个里面有默认参数,会出现二义性
void func2(int a = 10, int b = 10);
void func2(int a,int b)
{
}

//3.函数的占位
//如果有了占位参数,函数调用的时候必须要提供这个参数,但是用不到
//占位参数,没有很大的用处 ++重载会用到
//占位参数可以有默认值
void func3(int a, int = 1)
{
}

void test02()
{
    func3(10,1);
}

int main()
{
    //test01();
    test02();
    return 0;
}

函数重载

1.基本语法:

1)函数名称相同在同一个作用域,

2)函数参数的个数、类型、顺序不同

3)函数的返回值不可以作为函数的重载条件(二义性)

4)当函数重载遇到默认参数,注意避免二义性。

#include <iostream>
#include <string>
using namespace std;

//函数重载的基本语法
//在C++中函数名称可以重复
//必须在同一作用域,函数名称相同
//函数的参数 个数 或 类型 或 顺序 不同
void func()
{
	cout<<"this func is not argument"<<endl;
}

void func(int a)
{
	cout<<"this func is have argument (int a)"<<endl;
}

void func(double b)
{
	cout<<"this func is have argument(double b)"<<endl;
}

void func(int a,double b)
{
	cout<<"this func is have argument(int a,double b)"<<endl;
}

void func(double b,int a)
{
	cout<<"this func is have argument(double b,int a)"<<endl;
}

//返回值可以作为函数重载的条件吗?  不可以 在调用的是出现了二义性
//int func(double b,int a)
//{
//	cout<<"this func is have argument(double b,int a)"<<endl;
//}

//当函数重载碰到了默认参数的时候,要注意避免二义性
//void func2(int a, int b = 10)
//{
//	
//}
//
void func2(int a)
{
	
}

//引用的函数重载
void func3(int &a) //引用必须要引合法的内存空间
{
	cout<<"int &a"<<endl;
}

void func3(const int &a) //const也是可以作为重载的条件 int tmp = 10; const int &a = temp;
{
	cout<<"const int &a"<<endl;
}

void test01()
{
	func();
	func(1);
	func(1, 1.1);
	func(1.1, 1);
}

void test02()
{
	func2(10);
}

void test03()
{
	int a = 10;
	//func3(a);
	func3(10); //引用必须要引合法的内存空间
}

int main()
{
    //test01();
	//test02();
	test03();
    return 0;
}

2.函数重载的实现

编译器为了实现函数的重载,也是默认为我们做了一些幕后工作,编译器用不同的参数类型来修饰不同的函数名,例如:void func(); 编译器可能会将函数名修饰成_func,当编译器碰到void func(int a);编译器可能会将函数名修饰成_func_int,当编译器碰到void func(int a,char b);编译器可能会将函数名修饰成_func_int_char,编译器不同内部的处理方式也会不同,因为编译器如何修饰重载函数没有同一的标准,所以不同编译器可能会出现不同的内部名。

void func(){}
void func(int x){}
void func(int x,char y){}

以上三个函数在linux下生成的编译之后的函数名为
_Z4funcv()  //v 代表void,无参数
_Z4funci()  //i 代表int,参数类型为int
_Z4funcic() //i 代表第一个参数类型为int,c代表第二个参数类型为int

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值