1、函数的默认值
int Get(int a , int b , int c=2);
int Get(int a , int b=2 , int c);
int Get(int a=2 , int b , int c);
int Get(int a , int b , int c)
{
return a + b + c;
}
int main()
{
Get(20);
Get(20,20);
Get(20,20,20);
return 0;
}
(1)、从右向左 依次赋默认值
(2)、默认值只能赋一次
(3)、一般在声明上赋默认值
2、函数重载
//int Add(int, int); //?Add@@YAHHH@Z
//double Add(int, int); //?Add@@YANHH@Z
//double Add1(int, int); //?Add1@@YANHH@Z
//double Add1(double, double); //?Add1@@YANNN@Z
//double Add1(double, double, double); //?Add1@@YANNNN@Z
//double Add1(double,int); //?Add1@@YANNH@Z
//double Add1(int, double); //?Add1@@YANHN@Z
/*int Add(int a, int b) //?Add@@YAHHH@Z
{
return a + b;
}*/
/*double Add(double a, double b) //?Add@@YANNN@Z
{
return a + b;
}*/
int Add(double a, double b) //?Add@@YAHNN@Z
{
return a + b;
}
int main()
{
Add(10.1, 20.1);
//Add('a', 'b');
//Add(10, 20.1);
//Add(10.1, 20.2);
return 0;
}
函数符号生成规则:
C:符号生成只和函数名有关 不允许同名
C++:符号生成和函数原型有关:返回值、函数名、形参列表(类型、个数、顺序)
函数重载规则:
(1)、不能使编译器产生二义性、重载决议不能产生二义性
(2)、函数重载不依赖返回值(当函数名、形参列表相同时会使重载决议产生二义性)
函数重载的三要素:
(1)、同作用域
(2)、同名
(3)、参数不同
3、内联函数(inline)
inline void Print(int arr[], int len);
inline int Sum(int a, int b);
inline int Sum(int a, int b)
{
return a + b;
}
inline void Print(int arr[], int len)
{
if (len <= 0)
{
return;
}
Print(arr, len - 1);
cout << arr[len - 1] << " ";
}
int main()
{
int arr[] = { 3, 12, 32, 4, 32, 423 };
int len = sizeof(arr) / sizeof(arr[0]);
Print(arr, len);
Sum(10, 20);
return 0;
}内联:编译阶段 函数调用点直接代码展开,以代码膨胀(复制)为代价,仅仅省去了函数调用的开销,从而提高函数的执行效率
内联和static修饰的函数的区别:
(1)、本文件可见
(2)、内联:调用点直接展开代码、没有栈帧开辟和清理的开销
(3)、static:函数符号,static修饰的函数有开栈和清栈的开销内联和宏的区别:
(1)、内联在编译阶段展开,宏在预编译阶段展开
(2)、内联进行类型检查,安全检查,宏没有
(3)、内联是一种更安全的宏
内联的优点: 提高效率
内联的缺点: 代码膨胀、空间浪费大
内联的注意事项:
(1)、写在头文件
(2)、只在Release版本生效
(3)、递归,while,switch 内联只是给编译器的一个建议
(4)、内联是基于实现的不是基于声明的
开栈开销 小于 执行开销 不建议写成内联
开栈开销 大于 执行开销 建议写成内联
4、相互调用
C调用C++(1):
.c文件:
#include<stdio.h>
extern int Sum(int, int);
int main()
{
Sum(10, 20);
return 0;
}
.cpp文件:
extern "C"
{
int Sum(int a, int b)//_Sum .text
{
return a + b;
}
}C调用C++(2):
.c文件:
#include<stdio.h>
extern int MySum(int, int);int main()
{
MySum(10, 20);
return 0;
}
.cpp文件1(原.cpp文件):
int Sum(int a, int b)
{
return a + b;
}
.cpp文件2(中间文件):
extern int Sum(int, int);
extern "C"
{
int MySum(int a, int b)
{
return Sum(a, b);
}
}C++调用C(1):
.cpp文件:
#include<iostream>
using namespace std;extern "C"
{
extern int Sum(int, int);
}
int main()
{
Sum(10, 20);
return 0;
}
.cpp文件:
#ifdef __cplusplus
extern "C"
{
#endif
int Sum(int a, int b)
{
return a + b;
}
#ifdef __cplusplus
}
#endif
C++调用C(2):
.cpp文件:
#include<iostream>
using namespace std;extern "C"
{
extern int Sum(int, int);
}
int main()
{
Sum(10, 20);
return 0;
}
.c文件:
extern int Sum(int, int);
int Sum(int a, int b)
{
return a + b;
}extern "C": 包含的代码以C的规则处理
C调用C++:
(1)、C++能修改
.cpp中添加extern "C"
(2)、C++不能修改
添加中间层,中间层添加 extern "c"
C++调用C:
.cpp中添加extern "C"
不明确调用:
#ifdef __cplusplus
5、引用(别名)
#include<iostream>
using namespace std;
void Swap(int& a, int& b)(在形参定义时,需要通过指针来接受实参,可使用引用替代指针)
{
int tmp = a;
a = b;
b = tmp;
}
int main()
{
//int& a; // (错误、引用一定要初始化)
//int& a = 10; // (错误、引用引用的变量一定要能取地址)
const int& a =10;//(使用const ,当引用无法取地址的变量时、将变量存入临时变量、引用临时变量的地址)
int b = 10;
int& c = b;
c = 11;
b = 12;
cout << b << " " << &b << endl;
cout << c << " " << &c << endl;int e = 10;
int& f = e;
cout << ++e << " " << f << endl;int d = 10;
int& s = d;
int*p = &s;
int*q = &d;
int m = 10;
int n = 20;
Swap(n, m); (需要传地址来使实参完成交换,当使用应用时可直接传入实参)
cout << "m:" << m << endl;
cout << "n:" << n << endl;
return 0;
}
引用的底层以指针的方式来支持、在引用使用的地方、系统自带解引用过程
引用的使用:
(1)、引用一定要初始化
(2)、引用不可改变变量
(3)、引用引用的变量一定要能取地址
(4)、引用无法取地址的变量时、将变量存入临时变量、引用临时变量的地址(使用const)
(5)、引用只能访问引用变量所引用的内存块的内容
(6)、引用不能返回局部变量地地址
(7)、引用即起别名,不同于指针
6、const的区别
.c文件:
#include<stdio.h>
int main1()
{
const int a = gdata; //a = 20;(错误、C中常量不允许不能做左值(被修改))
int* p = &a; *p = 30; (正确、a没有做左值,可通过*p间接修改a的值)
return 0;
}
.cpp文件:
#include<iostream>
using namespace std;
extern const int gdata;(外部声明变量extern const int gdata = 10;)
int main()
{
int b = 10;
const int a = b; (定义const int a、用b来初始化、b为变量、用变量来初始化常量 、常量退化常变量)
cout << "a:" << a << endl;
cout << "b:" << b << endl;
int arr[a];//int arr[b] (因a已退化为常变量、不能做左值、不能用来初始化数组(数组初始化需要常量))const int c = 10;
int* p = (int*)&c; (定义一个int * p 并将const int c 强转为 int *型、p与c为同类型、可以进行赋值操作)
*p = 30; (p与c为同类型、可以通过修改*p修改c的值)
cout << "c:" << c << endl;const int d = gdata;
const int* q = &d; (定义const int * q q与d为同类型,可以进行复制操作)
//*q = 30; //q=a: (q与d 被const修饰,均不能修改)
printf("d: %d\n", d);
return 0;
}C中的const:
(1)、const修饰的变量称为常变量
(2)、编译阶段const不能做左值
(3)、extern const修饰的全局变量的符号是global
C++中的const:
(1)、const修饰的变量称为常量
(2)、编译阶段把用到常量的地方替换成常量初始化的值
(3)、const修饰的全局变量的符号是local
(4)、一定要初始化
(5)、不允许常量做左值
(6)、不能有间接修改内存块的风险
(6)、用变量来初始化常量 常量退化常变量
const的其它用法:
(1)、const - 形参:防止实参被修改、接收临时量
(2)、const - * 、const - **:杜绝间接访问修改常量内存块的值 (int **p -> const int ** p(*q p))
(3)、const - &:引用引用的变量不能取地址时常引用可以处理( 数值放到临时量(内存) 常引用引用临时量的内存单元)
(4)、const - 返回值:不能返回局部变量地址引用、不能返回局部变量地址、可返回局部变量的值