2021-07-07 C++笔记

1.内联函数

(1)内部链接的函数,能在编译期间进行代码展开的函数

PC程序计数器,指令一条一条运行 PC+1

当遇到一个函数如fun(),PC停在那个位置,跳转运行fun(),运行完,PC+1

fun()函数的生命周期只有一行

跳转运行函数很浪费资源和时间

inline int add(int a,int b)  //内联函数 
{    
    return a+b;
}
int main() 
{    
    int a=add(10,20);//当调用内联函数时,会自动把函数里的内容替换到主函数里    //既不影响程序可读性和封装性,也不浪费资源    //函数名→函数主体 
}

(2)限制:

内联函数中不可含有循环:展开会使代码量变得非常多

内联函数中不可能含有静态变量:静态变量的生命周期函数结束时不会结束,代码每次展开都会多一个静态变量

内联函数不可为递归函数

内联函数不可含有错误处理

①长度较长的函数不能声明为内联函数(不要超过5行,循环和递归)

②具有共用生命周期的变量的函数不能生命为内联函数(静态变量和异常处理)

(3)定义必须是在第一次调用之前

2.默认参数

C++在函数声明时允许对形参进行赋初值

int add(int a=1,int b=2)  //默认参数 
{    
    return a+b; 
} 
int main() 
{    
    cout<<add()<<endl;    
    retunr 0; 
}

防止反编译:使用add()不放参数,实际上需要参数,不可以通过反编译反推函数实现

当出现第一个默认参数时,后面的形参也必须是默认参数

int add(int a,int b=2,int c) //错误,c也必须是默认参数

3.函数占位参数

占位参数:没有函数名,占个位置的参数

int add(int a,int b,int)

占位参数没有意义,但调用必须放进去

add(1,2,3) ✔

add(1,2) ×

占位参数和默认参数混用int add(int a,int b,int =0)  

add(1,2,3) ✔

add(1,2) ✔

一个函数的形参列表有多种写法

4.函数重载

一种接口,多种实现(相同的函数名,不同的函数主体,不同的函数实现)

int add(int a,int b) //C语言里可以有相同的函数名
{
    return a+b;
}

float add(float a,float b)  
{
    return a+b;
}

char add(char a,char b)  
{
    return a+b;
}

//根据传参不同调用不用函数

int main()
{
    cout<<add(1,2)<<endl;
    cout<<add(1.2f,3.4f)<<endl;
    cout<<add('0','1')<<endl;
    return 0;
}

C语言里预处理 宏定义的替换 函数名的修改

fun→_fun 没有办法进行函数重载

C++里fun(int ,int ) →_int _int_fun

参数个数不同

参数类型不同

参数顺序不同

仅仅返回值不同,不可以构成重载!!!

int add(int a,int b)

float add(int a,int b)

默认参数在预处理修改函数名时不会纳入函数名

int fun(int a,int b)

int fun(int a,int b,int c=3) →_int _int_fun

add(1,2)会产生歧义

默认参数不可以重载

占位参数可以重载 占位参数占位

函数指针

函数指针可以精确地匹配重载函数

5.C++的类型转换运算符

C语言类型转换:

int a=97;

printf("%c\n",(char)a);//不会检查类型转换是否安全

补充:

比如int a=129;

char b=a;

//129超出char的取值范围,在char里值为-127,但在C语言里并不会检查这种错误

129低八位为原码10000001 补码10000001

转化为char第八位变成符号位,不变,对应反码为10000000(补码-1),对应原码即11111111,为-127

static_cast:

可用:

①具体普通类型的转换

②void*和其他类型指针之间的转换

不可用:

①不可用于具体类型指针之间的转换

②不可用于具体地址转换成指针

int a=129;
char b=static_cast<char>(a);//窄信息转换,可能会产生信息丢失
long c=static_cast<long>(a);//长信息转换,信息不会丢失
cout<<b<<endl;
cout<<c<<endl;
int *p=static_cast<int*>(malloc(sizeof(int)));//将void*转换为int *型的指针
void *p1=static_cast<void*>(p);//将int *转成void*
//不被允许的转换
//float *p2=static_cast<float*>(p);//具体类型的转换不被允许
//p=static_cast<int*>(0×ffff);//不可以转换具体的地址,程序员使用的地址是逻辑地址
//程序员很难确定正确的地址

//如何给固定地址的内存赋值?

void *p=(void*)(0xffff);//c语言里可以这么做

const_cast:将const类型转换成非const

const int a=100;
int *p=const_cast<int*>(&a);
*p=200;
cout<<a<<endl; //a=100,内存里的a确实被修改了,但编译时不会从内存里取a
cout<<*p<<endl; //*p=200
return 0;

reinterpret_cast:重新解释转换,暴力转换,非常的危险

int main()
{
    char str[]="hello";
    int *p=reinterpret_cast<int*>(str);//任何类型转换成任何类型
    cout<<*p<<endl;
    int a=100;
    int *p1=reinterpret_cast<int*>(a);
    cout<<*p1<<endl;
}

dynamic_cast:

dynamic_cast会检查转换的对象是否真的可以转换成目标类型,这种检查不是语法上的,而是真实情况的检查

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值