c++对c语言的增强
全局变量检测增强
int a;
int a = 10;//不能这么写
函数检测增强,参数类型增强,返回值检测增强,函数调用参数检测增强
int getRects(w,h)
{
}
void test
{
getRects(10,10,10)
}//不能这么写
类型转换增强
不匹配的数据类型会报错
struct增强
struct Person
{
int m_Age;
void plusAge();//c++中结构体可以加函数
}
void test
{
struct Person p;//c语言必须这么写
Person p;//c++可这么写
}
bool类型增强
bool flag;//只有真或假,非0的值转为1,0就为0
三目运算符增强
a > b ? a : b;//返回的是变量,c语言中返回的是值
但是三目运算符的运算级别较低,使用时记得加括号
const增强
c语言中,const修饰的变量为伪常量,编译器是会分配内存的。
c++中,const不会分配内存 const int a = 20;
可写为
int arr[a];//用来初始化数组
c语言const默认为外部链接
c++const默认为内部链接
extern const int a;//同时在两个作用域都这么声明才行
分配内存情况
1.取地址会分配临时内存
2.extern会分配内存
3.用普通变量初始化const变量,用数字初始化不会分配(const int a = 20;)
4.自定义数据类型,例如struct,class
尽量用const替换#define
define没有作用域概念,也没有类型
引用(联系dup2)
实质:就是起别名,一个指针常量
int &aref = a;// int* const aref = &a;说明了为什么引用必须被初始化
int &b = a;//引用初始化
写到左侧,叫引用,写到右侧,取地址。
引用必须初始化,且初始化后就不能够修改引用的变量,只能修改值。
对数组建立引用
void test()
{
int arr[5];
...//数组赋值语句
int (&parr)[5] = arr;//第一种方式
typedef int(ARRAYREF)[5];//一个具有5各元素的int类型数组
ARRAYREF &parr2 = arr;//第二种方式
}
引用传递与地址传递一样
void myswap(int &a,int &b)
{
...
}
main(){
myswap(a,b);
}
引用的注意事项
1.引用必须引一块合法的内存空间(NULL不合法)
int &a = 10;
2.不要返回局部变量的引用
int& dowork{
int a = 10;
return a;
}
int& dowork2{
static int b = 10;
return b;
}
main()
{
int &a = dowork();//这样做是错误的,第一次能成功返回,编译器做了优化,后面就不行了,dowork里面是局部变量
int &b = dowork2();//这样可以,并且函数调用可以作为左值
dowork2() = 1000;//相当于 b = 1000;
}
指针的引用
void allocat(Person **p)
{
*p = (Person *)malloc(sizeof(Person));
*p->age = 100;
}
void allocat2(Person* &p)
{
p = (Person *)malloc(sizeof(Person));
p->age = 100;
}
main()
{
Person* p = NULL;
allocat(&p);//二级指针
allocat2(p);//指针引用
}
常量引用
可以使用一种不合法的内存
const int &ref = 10;//加入了const后,编译器的处理方式为:int tmp = 10;const int &ref = tmp;
因此,可以通过修改指针的方式修改值,让const不起作用
int* p = (int *)&ref;
*p = 1000;
使用场景:用来修饰形参
void showvalue(const int &a)
{
a += 100;//如果只是想展示内容不修改,就加const修饰这个形参
cout << a << endl;
}
引用的好处
节省开销,不产生新的变量
内联函数(实际与宏的作用都一样)
宏函数的缺陷
运算结果可能与预期不相同
内联函数的注意事项
inline void func();//内联函数声明
inline void func();{
}//函数实现的时候也要加inline关键字否则就不算内联函数
内联函数用空间换时间
类里面的成员函数默认都会加inline关键字
内联函数其实就是给编译器一个建议,加上关键字,编译器不一定按照内联处理,不加关键字,也许编译起还会给你加inline
函数的默认参数以及占位参数
//函数的默认参数 参数后面 = ...
//函数参数注意事项,如果一个位置有了默认参数,那么这个位置开始从左往右都必须有默认参数
//传参如果有参数就用传入的参数,如果没有参数,就用默认值
void func(int a = 10,int b = 10)
{
cout << a + b << endl;
}
main()
{
func();//就不用传入参数了
}
函数声明与函数实现只能有一个有默认参数,不要同时出现默认参数
//函数占位参数
//如果有了占位参数,函数调用时必须要提供这个参数,但是用不到参数
//重载++有用
//可有默认值为 int = 任意值
void func(int a,int/int = 1......)
{
}
main()
{
func(10);
}
函数重载
函数名可以重复。
必须在同一个作用域,函数名称相同,函数的参数个数不同,类型不同或者顺序不同都可以重载。
返回值不可以作为重载的条件。
void func()
{
cout << "无参" <<endl;
}
void func(int a)
{
cout << "有参" <<endl;
}
main()
{
func();
func(1);
}
当函数重载碰到了默认参数的时候,要注意避免二义性问题
void func(int a,int b=10)
{
cout << "有默认参" <<endl;
}
void func(int a)
{
cout << "有参" <<endl;
}//这时会出现问题,导致调用时不知道该调用谁
引用的重载版本
void func(int &a)
{
cout << "有默认参" <<endl;
}
void func(const int &a)
{
cout << "有参" <<endl;
}
main()
{
func(10);//此时会调用const int &a说明 const
}
实现原理
编译器会在幕后改变函数名称
extern "C"浅析
#pragma once 防止文件重复编译
这时c++文件里就要加头文件
解决的问题就是在c++中调用c语言的函数