一、内联函数(了解)
1.0.概念
-
1)在c++中,预定义宏的概念是用内联函数来实现的,而内联函数本身也是一个真正的函数。
-
唯一不同于函数之处在于内联函数会在适当的地方像预定义宏一样展开,所以不需要函数调用的开销(占用空间,但是省去了函数调用时候的压栈,跳转,返回的开销)以空间换时间
-
-
2)内联仅仅只是给编译器一个建议,编译器不一定会接受这种建议。
-
如果没有将函数声明为内联函数,编译器也可能会将此函数做内联编译。一个好的编译器将会内联小的、简单的函数
-
1.1.宏函数的缺陷
1)
#define ADD(x, y) x+y
int a = ADD(10, 20)*2; // 预期是60,但是实际是50.即变成了x+y*2
----------------------------------------------------------
// 内联函数,inline是向编译器申请成为内联函数,不能在声明的时候使用,否则编译器会把函数当做普通函数
// 注意:能否成为内联函数,还得看编译器
inline int Add(itn x, int y)
{
return x+y;
}
// 编译器将会检查函数参数列表使用是否正确,并返回(进行必要的转换)。这些事预处理器无法完成的。
int b = Add(10, 20)*2; --> 60
2)
#define COMAPD(x, y) ((x)<(y)?(x):(y))
int a = 1; int b = 4;
int t = COMAPD(++a, b); // 结果为3,因为代码变为:int t = ((++a)<(b)?(++a):(b)) 连续进行两次++a
----------------------------------------------------------
inline int func(int x, int y) { return x<y?x:y; }
int t2 = func(++a, b); // 结果为2
1.2.什么情况不会成为内联函数
内联函数是以空间换时间,它会将函数体代码复制到调用处,以下情况可能会导致代码膨胀等问题
1)存在过多的条件判断语句
2)函数体过大
3)对函数进行取址操作
4)存在过多的循环语句
1.3.内联函数的好处
1)有宏函数的效率,没有宏函数的缺点
2)类的成员函数默认加上inline
二、函数的默认参数(重点)
2.1.含义
-
函数的默认参数就是给函数的形参赋值
-
增加函数的灵活性
-
2.2.函数的默认参数注意事项
1)函数的默认参数后面的参数必须都是默认参数
2)函数的声明和实现不能同时有函数的默认参数(会报错:重定义)
三、函数的占位参数(了解)
1)占位参数没有参数名,只有一个数据类型,且没办法在函数体中使用; 2)占位参数可以有默认值,当没有默认值时,必须在调用函数时给占位参数传值;
int func(int, int a = 10)
{cout << a << endl;}
四、函数重载(重点)
4.1.概念
1)在传统C语言中,函数名必须是唯一的,程序中不允许出现同名的函数。
在c++中是允许出现同名的函数,这种现象称为函数重载
2)目的是:为了方便的使用函数名
4.2.实现函数重载的条件
-
同一个作用域
-
参数个数不同
-
参数类型不同
-
参数顺序不同
-
// 参数个数不同
void func(){}
void func(int a){}
// 参数的类型不同
void func(char c){}
// 参数的顺序不同
void func(int a, double b){}
void func(double b, int a){}
4.3.调用重载函数的注意
1)严格的类型匹配,如果类型不匹配,那么尝试转换,转换成功就调用,失败就报错
double 不能转换成 int char char 可以转换成 int
2)函数重载和函数的默认参数一起使用,需要注意二义性问题
void myfunc(int a, int b = 0){}
void myfunc(int a){}
int main()
{
myfunc(10); // err,二义性问题,不知道调用哪个函数
}
3)函数的返回值不作为函数重载的条件
编译器是通过你调用函数时,传入的参数来判断调用重载的哪个函数,无法判断返回值
五、函数重载的原理(重点)
1)函数重载的原理是在汇编时,给各个函数取别名,C语言不能重载的原因是没有取别名
// C语言
void func(){}
void func2(){}
----------------------------
汇编
_func:...
_func2:...
// c++
void func(){}
void func(int a){}
void func(int a, double){}
----------------------------
汇编
__Z4funcv:
__Z4funci:
__Z4funid:
六、C++调用C语言的函数(重点)
1.c++的函数在汇编时,与C语言的函数名字有不同
C++: __Z4func() C语言: _func()
所以,c++文件在调用C语言函数的时候,编译器会找__Z4开头的,找不到便报错
2.解决方案
/* 声明文件:test.h */
#pragma once
// 告诉C++编译器,找下面的函数,要以C语言的方式去寻炸
#ifdef __cplusplus
extern "C"
{
#endif
void func(); // C语言的 函数声明写在这里
#ifdef __cplusplus
}
#endif
七、类和对象的概念(重点)
1.类是自定义数据类型,是C语言的结构体进化而成的
2.对象是类实例化出的,即用数据类型定义的一个变量
八、类的封装(重点)
8.1.概念
封装是把属性(变量)和方法(函数)封装到类内,然后给这些数据赋予权限
8.2.为什么要有封装
1)防止乱调用函数和变量,出现错误
2)维护代码更方便
8.3.访问权限
1.在类的内部(作用域范围内),没有访问权限之分,所有成员可以相互访问
2.在类的外部(作用域范围外)。访问权限才有意义:public,private,protectede
-
在类的外部,只有public修饰的成员才能被访问,在没有涉及继承与派生时,private和protected是同等级的,外部无法访问
访问属性 | 属性 | 对象内部 | 对象外部 |
---|---|---|---|
public | 公有 | 可访问 | 可访问 |
protected | 保护 | 可访问 | 不可访问 |
private | 私有 | 可访问 | 不可访问 |
3.在继承时,子类的类内可以访问父类的保护权限的成员
8.4.尽量把成员属性权限设置为私有
1.可以控制属性读、写权限
2.可以赋予客户端访问数据的一致性
-
客户只需要通过访问public权限的函数,不需要考虑:访问的成员需不需要添加
3.可以保护属性的合法性
-
客户赋予的值如果不合法,便不会赋值
九、类和结构体的区别(了解)
-
结构体的默认权限是公有的
-
类的默认权限是私有的