嵌入式面向对象编程
学习目标:掌握嵌入式GUI(图形化界面)开发-QT库
1. 解决命名冲突
1、c语言中解决命名冲突的方法:使用static关键字
- 作用:
修饰局部变量:延长局部变量的生命周期,程序结束后再释放
修饰全局变量:该全局变量只能在本文件访问,不能在其他文件访问
修饰函数:该函数只能在本文件调用,不能在其他文件调用
2、c++语言解决命名冲突:命名空间
-
命名空间的定义:namespace 名字{变量、函数}
-
命名空间的使用:
-
使用作用域限定符:使用命名空间的名字::变量名或者函数名
-
使用using关键字导入命名空间:using namespace 命名空间;using 命名空间::变量名或者函数名
-
命名空间注意事项:
(1)源文件不能访问其他文件的命名空间(命名空间中存在定义)-------(及时放在头文件里,然后包含之后都无法访问)
(2)当多个源文件的命名空间名字相同时:如果没有出现重复的变量名或者函数命名,系统会合并两个命名空间(但是实际上并不是合成一个命名空间,只是能通过编译);否则会报错#include
//static int count = 2;using namespace std;//标准命名空间
输入与输出
cin: 输入流
cout: 输出流
cerr: 错误流
clog:日志流 流对象
流运算符: >>输入 <<输出
cout << "hello world"<< end1;
cout << "num = " << num << end1;
int fd = open("a,txt",O_CREAT | O_RDWR, 0655);
if(fd == -1)
{
cerr << "open a.tet error!" << end1;
}
cout << "open a.txt success!";
while(1);
//printf:行缓冲:满一行才输出或者遇到‘\n’
//scanf:输入前,刷新缓冲区
//使用Printf调试时,一定要加‘\n’
int num;
char ch;
char scr[100];
cin >> num;
cin.get();
//getchar();
cin >> ch;
cin.get();
C++对C语言的升级
- 基本语句的升级
- for语句:优化循环变量的作用域
g++ demo.cpp --std=c++17
关键字的升级
-
register关键字的升级:若对register变量取地址,会将该变量重新保存到内存中;
register:尽可能的将该变量保存到CPU内部寄存器中,从而省去从内存中抓取数据的时间,提高程序的运行效率
使用注意事项:
1、只能修饰局部。不能修饰全局变量和函数
2、register修饰变量,不能通过&获取该变量的地址
register int count = 6;
int *p = &count;
3、register修饰的变量类型必须是CPU所能够接受的数据类型 -
const关键字的升级
const:修饰变量,只读变量
const int num = 5;
const关键字的升级:const修饰的是常量
指针地址之间的赋值,必须是const对const;
const int num = 5;
const int *p_num = #
//*p_num = 7;
-
auto关键字的升级
c语言中:自动变量,只是用来说明该变量的作用域;相当于局部变量
c++中:类型推导,实现高效编程
auto ch1 = 'a';
auto str = "hello world";
auto d = 1.12345;
string s11 = "hello";
string::iterator it = s1.begin();
auto it2 = s1.begin();
-
using关键字的升级:替代c语言typedef的关键字
typedef关键字的作用:给类型重命名的;提高代码的可读性、移植性
using Int = int;//typedef int Int;
using Len= int;//typedef int Len;
using P_FUNC = int (*)(int,int); //typedef int (*P_FUNC)(int,int);
Int c;//int c;
Len c2;
add(6,5);
P_FUNC p_func;//int (*p_func)(int,int) = add;
p_func(6,5);
类型的升级
-
引入了bool类型
bool flag = false;
-
引入了“引用“
引用:给变量起别名,定义引用必须初始化,一旦绑定就不能再次绑定到其他变量上;
作用:解决函数传值和传地址的问题
应用场景:作为函数的形参;作为函数的返回值(函数的调用可以做左值)
int left = 5;
int right = 6;int &l_left = left;
l_left = right
l_left++;
//交换值
void swap(int &left,int &right)
{
int temp;
temp = left;
left = right;
right = temp;
}
int & test()
{
static int num = 5;
cout << num << end1;
return num;
}
int temp = test();
test() = 10;
test();
//输出:
5
5
10
5
-
常引用:const修饰的引用;绑定常量(只读)
-
C++引用的分类:左值引用(&);只能绑定左值、右值引用(&&):只能绑定右值
左值:可以取地址可以修改
右值:不能取地址,不能修改
std::move()的作用:将左值转换为右值
为什么要引入右值引用?实现对象移动,解决临时对象拷贝开销的问题
int num = 5;
int &l_num = num;//左值引用
int &&r_num = 5;//右值引用
int &&r_num2 = std::move(num);//左值转为右值
引用是不是数据类型?(不是)
它占不占用内存空间?(运行时不占用运行空间,编译时预留内存空间)
指针和引用的区别?
引用是别名,指针是地址
指针在运行时可以改变所指向的值,而引用一旦与某个对象绑定后就不再改变。意思是:指针可以被重新赋值以指向另一个对象,但是引用则总是在初始化时被指定的对象,以后不能改变,但是指向的内容可以改变。
什么是对象移动?对象移动的作用?
移动而非拷贝对象。如此做的好处就是,在某些情况下,对象拷贝后就立即被销毁了,此时如果移动而非拷贝对象会大幅提升性能
对象移动、移动构造函数、移动赋值运算符
malloc\free
引入了new、delete运算符来代替malloc、free
char *ptr = new char[100];
char *ptr1 = new char(‘a’);
int *p = new int(5);
delete [] ptr;
delete ptr1;
ptr = nullptr;//NULL
ptr1 = nullptr;
malloc free vs new delete
1、malloc按照字节为单位,new按照数据类型的个数为单位
2、malloc不能初始化内存,new能
把指针里分配好的一百个字节清空
拷贝
释放
函数的升级
引入inline关键字修饰函数:用(内存)空间换运行时间
inline int add(int a,int b);//内联函数
{
return a+b;
}
add(6,5);
add(6,5);
add(6,5);
add(6);
//…
引入默认参数:可以给形参设定默认参数 规则:默认参数的右边的参数必须全为默认参数
可以实现函数重载:可以使用相同函数名,重载规则:形参的个数、类型或者顺序不同;
注意事项:函数返回值不能作为重载条件,默认参数会影响重载规则
int add(int a,int b,int c)//个数不同
int add(char a,cha b)//类型不同
int add(int a,double b)//顺序不同
int add(int a,string b,int)//占位参数