r无符号长整形:(定义一年有多少秒)
```c
#define SECOND_PRE_YEAR (365*24*60*60)UL
```
宏:输入两个数,返回较小的数的值
```c
#define MIN(A,B) ((A)<=(B)?(A):(B))
```
宏的副作用:出现边际问题或者括号问题
宏可以嵌套,可以有参数
DMA:内存搬移工具,是一种高速传输的数据操作,既不通过CPU,也不需要CPU干预,整个数据传输操作在一个叫做“DMA控制器”的控制下进行,分为:
1. 内存到设备(uart串口),内存到内存,设备到内存(adc数模转换器)
2. 三要素:源地址,目标地址,数据量
3. 弊端:因为允许外设直接访问内存,从而实现对总线的独占,这在实时性强的硬实时系统的嵌入式开发中会造成中断延时过长
4. 程序中断和DMA不同点:
- 中断方式通过程序传输数据,DMA不使用程序直接靠硬件实现,传输速度快
- 中断方式必须切换程序,要进行cpu的保护和恢复操作,DMA不改变CPU现场,额外花销少
- DMA请求的优先级比中断请求高,CPU优先响应DMA请求
- 中断方式不仅具有I/O数据传送能力,而且还能处理异常事件,DMA只能进行I/O数据传送
数据类型的大小:
1. int:16位(2)是32位、64位(4)一半
2. long:16、32位(4)是64位(8)一半
3. 指针:16位(2),32(4),64(8)
构造数据类型
1. 结构体(struct):通常是4字节对齐
2. 枚举类型(enum):默认值为0开始,下一个值等于上一个值+1
3. 联合体(共用体union):联合体成员共用一段空间,大小等于成员最大所占空间
预处理器标识 #error 目的是:停止编译并显示错误信息
存储:
1. ram掉电丢失数据,访问数据快,适合执行程序
2. flash掉电不丢失数据,访问数据慢,适合存放数据和程序
死循环:
```c
while(1)
{;}
for(;;)
{;}
Loop:
...
goto Loop;
```
c语言实现的算法可以没有输入,但一定要有输出
反码等于原码取反,补码等于反码加1,计算机采用的是数值的补码
函数传参时:
1. 参数是指针:地址传递,实参将地址传给了形参,实参和形参是同一地址,指向的是同一内存空间,可实现通过调用函数使得变量值发生改变
2. 参数是普通变量:值传递,函数调用过程中,形参重新申请了新的内存空间,实参将值传给形参
链表和数组的区别:
1. 从逻辑上说,这两种数据结构都属于线性表,但是物理存储结构有所不同,数组占用连续的空间,支持随机访问,但插入删除也比较低效,链表不一定连续,空间可扩容
2. 访问时数组因连续能随机存储,使用下标,而链表只能顺序访问,访问时的时间复杂度分别为O(1)和O(n)
回调函数:
1. 通过函数指针调用的函数。把函数的指针作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数的时候,就叫做回调函数。
指针函数和函数指针的区别:
1. 一个是返回指针的函数,一个是指向函数的指针(指向函数的入口地址)
指针数组和数组指针的区别:
1. 数组指针:首先是一个指针,指向一个整型的一维数组
2. 指针数组:首先是一个数组,每一个数组元素都是一个指针
绝对地址0x5a00存入一数值0xaa55
```c
int *p = (int *)0x5a00;
*p = 0xaa55;
```
头文件:ifndef /define / endif 作用:防止头文件被重复包含
线程和进程的区别:
1. 开销不同,每个进程都有独立的代码和数据空间,每个线程都有自己独立的运算栈和程序计数器,但他们切换时开销不同,进程大,线程小
2. 进程运行在操作系统中,线程运行在进程中,能同时运行多个进程和多个线程,但每个时间片中只有一个进程或线程执行
3. 内存分配不同,cpu会为进程分配内存,不会为线程分配内存,线程用进程的内存
4. 根本区别是:进程是操作系统资源分配的基本单位,线程是任务调度和执行的基本单位,是一种轻量级的进程,线程是组成进程的基本单位
线程:
1. 一种轻量级的进程
2. 创建:pthread_create(4),回收:pthread_join(2)
结束:pthread_exit(1),取消:pthread_cancel(1)
3. 线程同步:多个线程同时使用同一个资源,使用线程锁解决
进程间的通信
1. 管道(无名管道pipe(父子进程)—— 半双工,有固定读写端,可使用lseek函数,有名管道fifo(任意进程间)半双工,)
2. 消息队列:由消息组成的链表,存放在链表中
3. 信号量:(信号量是一个计数器,控制多个进程对共享资源的访问,作为一种锁机制)
4. 共享内存:由一个进程创建,多个进程访问,最快的IPC方式,效率最高
5. 套接字:可用于不同机器间的进程通信
守护进程:
1. 运行在后台的一种特殊进程,独立于终端并且周期性的执行某种任务或等待处理某些发生的事件
2. 创建守护进程:
- 创建进程,退出父进程(fork(),exit())
- 脱离控制终端,登录会话和进程组(setsid)
- 禁止进程重新打开终端,关闭打开的文件描述符
- 改变当前的工作目录
- 重设文件掩码
发送时指定一种存储方式发送(网络字节序),接收时把数据转换为主机的存储方式
UDP通信:
1. 无连接,不可靠,可以对任意对象收/发数据,面向数据报的通信
(socket(3)、bind(3)、sendto(6)、recvfrom(6)、close(1))
2. 可进行UDP广播,TCP没有(因为一对一)
2. socket套接字类型:SOCK_STREAM--TCP,SOCK_DGRAM--UDP
TCP通信:
1. 有连接,可靠,一对一,面向字节流(可靠:拥塞控制,流量控制,超时重传)为了防止线程或进程对资源进行抢夺,加锁(互斥锁)
2. (socket(3)、bind(3)、(connect(3) / listen(2)、accept(3))、(read(),write(),send(),recv())、close())
TCP三次握手:
1. 客户端向服务器发送请求报文,请求建立连接
2. 服务器向客户端发送确认报文
3. 客户端向服务器端发送确认报文
TCP连接释放四次挥手:
1. 客户端发送tcp连接释放报文
2. 服务器端收到断开请求,发送确认报文
3. 服务器端发送连接释放报文
4. 客户端收到连接释放报文,发送普通确认报文
服务器模型:
1. 循环服务器:一次只能处理一个客户端请求
2. 并发服务器:一次可以处理多个客户端请求
- 多进程/多线程:实时性高,资源占用大
- 多路复用:实时性差,资源占用小(selsec、Poll、Epoll,都是监控无上限,只有Epoll可以获取有时间发生的fd)
TCP/IP协议OSI模型:物数网传会表应
1. 分层模型(4):
- 应用层:负责提供数据
- TCP层(传输层):负责数据安全,端口号识别目标
- IP层(网络层):提供端到端,负责数据报在网络中传输,IP地址识别主机
- 网络接口层:根据不同物理介质,将数据转换成不同信号发送出去
窗口:TCP头里,主要用于流量控制,防止数据溢出
组播广播区别:广播是所有人能听到,组播想接收消息需要进入特定组,广播地址:192.168.1.255
路由器工作在IP层(网络层),负责寻址,交换机工作在数据链路层
1. ARP协议:根据IP地址获取物理地址的协议
2. ICMP协议:TCP/IP协议族下子协议,用于在IP主机,路由器之间传递控制消息(ping)
信号量:
1. 进程间同步互斥,通过一个变量来管理进程的先后执行顺序(semget)
进程五种状态:
1. 创建(初始),就绪,运行,阻塞(挂起),终止
嵌入式:
1. 嵌入到受控器件内部,使其具有一定智能化的一套系统,以硬件为中心对成本,体积,功耗,稳定性,可靠性,实时性等有特殊要求的软硬件可裁剪的系统
ARM架构:
1. 精简指令集,低功耗,高性能的16/32微处理器
2. CPU 7种模式:用快外管数系未
3. 共有37/40个寄存器,PC(程序计数器R15),LR(链接寄存器R14),SP(栈指针寄存器R13),CPSR(程序状态寄存器)
4. 异常(4大步3小步)
- 备份cpsr到对应spsr
- 设置cpsr()(重置cpu为ARM状态,设置模式位为对应的模式,禁止某些中断)
- 保存(pc-4)到对应模式的lr中
- 设置pc到对应异常向量的地址
系统移植
1. uboot(3.14),系统内核,根文件系统
内核移植过程:
1. 搭建交叉开发环境
2. bootload的选择和移植
3. 内核的配置、编译和移植
4. 根文件系统的制作
系统启动流程:
1. 加载内核----启动初始化----确定运行级别----加载开机启动程序----用户登录--
--进入login shell-----打开non-login shell
中断响应流程:保护断点,寻找中断入口,执行中断程序,之后恢复现场继续执行
异常触发后:
1. 硬件:
- (4大步)备份cpsr,修改cpsr,保存返回地址到LR,pc=异常向量表的对应位置
2. 软件:
- 跳转到异常向量表(do_irq)
- 保护现场,回复现场(do_irq,bl do_irq)
- c函数,判断哪个硬件触发的中断,调用对应的具体硬件中断处理函数
- 清除中断源,访问特殊功能寄存器
ARM如何切换模式:直接设置CPSR寄存器的后五位,也可以通过外部中断或者异常处理切换,例如发生中断后切换到irq模式
中断是由外部事件引起(I/O中断,时钟中断,硬件故障),异常是由内部执行指令引起(7大异常)
驱动开发:
1. 如何实现字符设备驱动:
- 向内核申请一个设备号
- 创建一个字符设备驱动对象
- 创建一个字符设备文件节点
2. 内核中的锁
- 原子变量:整数,用于计数
- 互斥锁:可以睡眠,节约cpu,实时性差
- 自旋锁:不可睡眠,浪费cpu,实时性强
3. IO模型:
1. 阻塞IO:大部分程序(没有数据读写,阻塞等待)
2. 非阻塞IO:如果不能立即完成读写,立马结束返回,不进行IO
3. IO多路复用:创建文件描述符表进行管理
4. 异步通知:进程等待内核通知信号,收到信号,读取数据
4. 中断下半部分:
随着驱动功能的添加,中断功能承担任务越来越多,无法保证快进快出,大部分交给中断下半部分(使用中断下半部分---将任务推迟)
实现方式:
- 软中断:不能睡,优先级高,内核专用
- tasklet:不能睡,优先级高,驱动开发者专用
- 工作队列:能睡,优先级低
5. Kmalloc和Vmalloc的区别:两者都用于内核
- Kmalloc:分配的资源32b-128k,物理地址和虚拟地址都能连续访问,且效率很高
- Vmalloc:申请的空间很大,从内存中简陋组成一个你需要的空间,物理地址可能不连续,虚拟地址连续,效率低
6. Linux设备:
- 字符设备:只能一个一个字节读写的设备,无随机读取,读取数据按先后
- 块设备:可以从设备任意位置读取一定长度数据的设备,如硬盘
- 网络设备:任何网络事物都通过一个接口进行,能与其他主机交换数据
7. 总线协议
总线:连接设备和驱动
- 并行总线:数据同时发送,没有固定格式,传输速度快,成本高,不适合远距离
- 串行总线:只能各位逐次收发,速度慢,便于远距离传输
驱动进入总线bus,总线遍历链表,发现合适总线,交给驱动配对,成功init,失败无init,继续遍历
- UART串口总线:RXD、TXD、GND三根线,起始信号+数据为8bit+校验位+停止位,单工,因为无时钟线,要求有自己的时钟源,需要提前约定对应的波特率,是一种异步传输协议,通用串行数据总线,异步收发传输器
- i2c:时钟线和数据线,发送信号(起始、结束、应答信号)和数据(读、写数据),不能同时收发,半双工,7bit地址位+1bit读写位,是一种同步传输协议,传输速率由时钟线上的时钟频率决定,标准模式下可达100kb/s-400kb/s,最高可达3.4mb/s
- spi:同时收发,全双工,(四根线:时钟线CLK,主发从收MOSI,从发主收MISO,片选CS)是一种同步传输协议,一对多时i2c更具优势,但是速率要低于spi,有的器件已达50mbps,(1M-10M)
- usb:通用串行总线,支持设备的即插即用和热插拔功能
二维数组初始化时,二维数组的大小可以不指定,一维数组大小必须指定
数据声明:
```c
一个整型数:// int a;
一个指向整型数的指针:// int *a;
一个指向指针的指针:// int **a;
一个有十个整型数的数组:// int a[10];
一个有十个指针的数组:// int *a[10];
一个指向十个整型数数组的指针:// int(*a)[10]
一个指向函数的指针,该函数有一个整型参数并返回一个整型数:// int (*func)(int a)
一个有十个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数:
// int (*a[10])(int)
```
static 的作用:
1. 修饰全局变量:表示这个变量只可以在这个模块中使用
2. 修饰局部变量:表示这个变量只能在局部范围使用,但超出范围依然占内存,还存在,多次调用时不会重复初始化,访问同一个空间
3. 修饰函数:表明这个函数只能在这个模块里调用,其他模块不能调用
3. static inline类似宏函数,该参数修饰的函数,在被调用的地方自动展开,减少函数调用的层次,节省cpu资源,但是会使程序体积变大
3. 可以在可被多个.c文件包含的头文件中定义全局变量,但要加上static,建议不要定义,只做声明
const 的作用:
1. 意味着只读。保护不希望被改变的代码,防止被无意的代码修改。
也许能产生更紧凑的代码。
2. 修饰变量时一定要初始化,否则后面就不能再赋值了
3. 修饰变量占用内存,define不占用内存,define在编译阶段展开,const在编译运行阶段使用
```c
const int a;
int const a;
const int *a;
int * const a;
int const * a const;
```
总结:左定值右定向
volatile 的含义;
1. 这个变量可能会被意想不到的改变,修饰变量,让编译器不会去假设这个变量的值,小心的重新读取这个变量的值,不会去用保存在缓存里的备份
1. 主要使用在:中断和进程共享变量,进程和进程,寄存器
注意:
1. 一个参数既可以是const,还可以是volatile,表示可能会被意想不到的改变,不应该试图去修改
2. 可以修饰指针,例子是中断子程序修改指向buffer的指针
extern 的作用:
使用其他文件函数外的变量
1. 扩展外部变量的作用域,扩展到其他文件或在同一个文件里
2. 将外部函数的作用域扩展到其他文件(函数名前无static)
3. 声明变量时不要对其赋值
4. 只能够定义一次,可以声明许多次,即使不初始化也为0
4. 可引用一个已经定义过的全局变量,还可以使用引用头文件的方式使用全局变量
register:寄存器型存储,表示把变量存储在cpu中,是否能存储由cpu决定
struct:声明一种构造类型,存在字节对齐
typedef:在编译时对类型取别名
位操作:
1. 清除和赋值:值 |= 值 &(~值) | 值<<值
访问固定的内存位置:设置绝对地址为0x67a9为0xaa55
1. ```c#
int *ptr;
ptr = (int*)0x67a9;
*ptr = 0xaa55;
```
中断(ISR):
1. ISR 不能返回一个值,不能传递参数,浮点一般是不可重入的
2. ISR应该快进快出,可以说不能做浮点运算,printf()也是一样
2. 流程:cpu正在执行,产生中断,cpu跳转到异常向量表,跳转到中断处理程序,找到中断号,执行,返回
unsigned 的运用:
1. 当表达式中存在有符号类型和无符号类型时所有的操作数都
自动转换为无符号类型
2. 设置一个数为0xFFFF要写成~0,涉及到处理器字长的问题
动态内存分配:
1. malloc(0) 可返回一个空指针,也可返回一小片地址(由机器决定)
2. ```c
memcmp
//比较两块内存中的字符
int memcmp( const void *buf1, const void *buf2, size_t count );
memset
//将内存块设置为指定的字符
sprintf
//将格式化的数据写到字符串
```
new和malloc的区别:
1. 申请的内存所在位置不同。一个是自由存储区(new),一个是操作系统的栈区(malloc)
2. 返回类型安全性不同。一个是返回对象类型的指针,无需类型转换,一个是返回void*类型,需要强转成我们需要的类型
3. 内存分配失败时的返回值不同。new会抛出bac_alloc异常,malloc会返回NULL
4. new无须指定内存块的大小,malloc需要显示的指出所需内存的大小
标准IO三种缓冲:
1. 全缓存(),行缓存(\n,stdin,stdout),无缓存(stderr)
2. fopen(w/r/a),fclose,fgetc,fputc,fread,fwrite
文件IO:
1. 不带缓冲,每次读写直接使用内核的系统调用
2. open(路径,O_RDONLY/O_WRONLY|O_CREAT,777),close,read,write
3. 文件偏移:lseek(文件描述符,偏移量,移动开始位置)
静态库(后缀名.a,用ar命令):
1. 编译可执行程序时,把库的二进制代码直接连接到目标代码中,运行时不需要库
2. 使用:gcc 源文件 -o 目标程序 -L库路径 -I库名
动态库:
1. 不会把库的内容连接到目标代码中,只会创建一个链接,执行到库再把库拿出来
2. 制作好库后拷贝到/usr/lib,然后提供当前库的路径进行保存,当前终端指定库路径
动态内存:new,delete----------堆内开辟空间
1. delete counter释放堆区内存时,释放的是变量或对象的内存空间,counter本身还存在,变成空指针
程序的内存分配:
1. 栈区(stack)—由编译器自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。iOS栈区大小是2M
2. 堆区(heap)—一般由程序员分配释放,若程序员不释放,程序结束时可能由 OS 回收。free()释放,内存泄露发生在堆区
3. 全局区(静态区)(static)—全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。程序结束后由系统释放。
4. 文字常量区—常量字符串就是放在这里的。程序结束后由系统释放。(只读存储区)
5. 程序代码区—存放函数体的二进制代码
堆和栈的区别:
1. 堆是程序员申请和释放,申请空间较大,相对较慢,向高地址扩展的不连续区域,存放内容程序员自己安排。
2. 栈是编译器自动分配和释放,申请空间小,申请速度快,向低地址扩展的连续区域,存放内容多数有自动进行。
TCP 和 UDP 之间的区别:
1. TCP:传输控制协议,是一个基于连接的可靠的字节流服务,双方交换数据是必须先建立连接,才能传输数据。超时重发,数据校验,丢弃重复数据,保证数据从一端传到另一端。
2. UDP:用户数据报协议,是一个简单的面向数据报的运输层协议,不可靠,效率高。
全局变量储存在静态数据区,局部变量在堆栈中。
堆栈溢出一般是由什么原因导致的:
1. 没有回收垃圾资源
2. 层次太深的递归调用
进程间通信的方式都有哪些,有何区别:
1. 管道,socket,共享内存,消息队列,信号量级
2. 共享内存:效率非常高
哪些情况会导致内存泄露?如何避免内存泄露:
1. 堆内存泄露,一般是指 malloc,realloc,New,而未对应的用free 或 delete 释放。
2. 系统资源泄漏,指程序使用系统分配的资源或函数,如 socket,handle 等,而未用相应的函数释放掉。
避免方法:养成良好的编码习惯,在涉及内存代码编写时要谨慎。
简述嵌入式 Linux 系统开发流程:
1. 操作系统的裁剪。
2. 嵌入式操作系统内核的配置和编译。
3. 文件系统的建立。
4. 用户程序的编写和简单的仿真调试。
5. 整体系统的目标板仿真调试。
6. 系统下载和脱机运行。
C 语言实现冒泡排序算法:
```c
#include<stdio.h>
int main()
{
int i,j,temp;
int arr[10] = {1,2,4,3,6,8,5,7,9,0};
for(i=0;i<10;i++)
{
printf("%d",arr[i]);
if(i==9)printf("\n");
}
printf("=====================\n");
for(j=0;j<9;j++)
{
for(i=0;i<9;i++)
{
if(arr[i]<arr[i+1])
{
temp = arr[i];
arr[i]=arr[i+1];
arr[i+1] = temp;
}
printf("%d",arr[i]);
}
printf("%d\n",arr[9]);
}
return 0;
}
```
编写反转字符串函数:
```c
int Reverse(char *str)
{
if(str == NULL)
return -1;
int length = strlen(str);
int i = 0;
int j = length -1;
while(i<j){
char temp = str[i];
str[i] = str[j];
str[j] = temp;
i++;
j--;
}
return 0;
}
```
n阶阶乘的递归算法
```c
int func(n)
{
if(n == 1)
return 1;
return n*func(n-1);
}
```
测试大小端问题:
```c
union{
short a;
char ch[2];//ch[0]读取的肯定是 低地址, 通过打印来发现低字节存放的是 a的高位还是低位
}var;
var.a = 0x1001;
printf("low 8 bit is %d\n",var.ch[0]);
```
字符串比较函数
```c
int strcmp( const char *s, const char *d)
{
int i = 0;
if(!s||!d){return -1;}
while(s[i]&&d[i])
{ //都不为空,依次减
if(s[i]-d[i])
{
return -1;
}
i++
}
//代码到这里,说明至少有一个为null,另一个也得为空才行
return s[i]-d[i];
}
```
已知 strcpy 函数的原型是
char *strcpy(char *strDest, const char *strSrc);
其中 strDest 是目的字符串,strSrc 是源字符串。
1、不调用 C++/C 的字符串库函数,请编写函数 strcpy
```c
char *strcpy(char *strDest, const char *strSrc);
{
if((strDest==NULL)||(strSrc==NULL)) // 2 分
return NULL;
char *address = strDest; // 2 分
while( (*strDest++ = *strSrc++) != ‘\0’ );// 2 分
return address ; // 2 分
}
```
单链表逆序
```c
int list_reverse(struct node *pthread)
{
struct node *p;
struct node *u;
struct node *q;
p = pthread->next;
pthread->next = NULL;
while(p){
//insert p,behind pthread
u = p->next;
q = pthread->next;
pthread->next = p;
p->next = q;
p = u;
}
return 0;
}
```
文件目录命令:
ls + 选项 + 参数(目录路径)
shell编程:
1. 将shell命令按照一定的逻辑、顺序组织在一个文件中,组合成一系列完整的功能要求,执行文件,就把其中的命令依次执行
gcc编译步骤:
预处理(转换预处理命令),编译(源代码转换汇编),汇编(汇编转目标文件二进制),链接(二进制代码组合成可执行程序 )
指针:
1. 野指针:指针记录的地址空间不明确:int *p
2. 空指针:指针记录的是NULL的地址,不能在这个地址进行任何操作,值为0,目标和地址不为0
3. 万能指针:可以存储任意类型的指针值
3. 智能指针:是一个类,用来存储指向动态分配的对象指针的类,把一个计数器与类指向的对象相关联,引用计数跟踪该类有多少个对象的指针指向同一个对象,拷贝时增加引用计数,对对象赋值时减少左操作数所指对象的引用计数,调用析构函数时减少引用计数,减少至0则删除对象。
指针变量存储不了整个字符数组,只存储了数组首地址
1. 指针数组:int *a [ * p , *q]
2. 数组指针:int (*p)[5]
指针和引用的不同点:
1. 引用在定义时必须初始化,指针不需要,有空指针无空引用,有多级指针,无多级引用
2. sizeof引用是指引用类型的大小,而指针是指地址空间所占字节数
3. 引用自加是实体增加1,指针自加是指针向后偏移1个类型大小。
C++:
多态:一种接口,多种方法
命名空间:主要解决标识符重名的问题,其实是全局作用域的一个片段
封装:
1. 私有成员(属性和方法):对类的外部、派生类不可访问,对内部、友元函数可访问
2. 公有成员:访问无限制
3. 保护成员:对外部不可见,对内部、友元、派生可见
静态成员:
1. 编译阶段分配内存在全局区,只能访问到更改后的数据
2. 类内声明,类外初始化,c++禁止类内初始化,必须初始化
3. 所有对象共享同一份数据
4. 静态成员函数只能访问静态成员变量
空对象占用空间为1
只有非静态成员变量才属于类的对象,静态成员变量、静态/非静态成员函数不属于
this指向被调用的成员函数所属对象(指向当前类),静态成员函数没有this指针
静态不可以调用非静态,非静态可以调用静态
const修饰函数(常函数),不可以修改成员属性,须加mutable
const修饰对象(常对象),只能调用常函数
友元函数:(friend)
1. 让函数可以访问类中的所有成员,是给外部提供一个可访问的窗口,在类内声明但不属于这个类,没有this指针
构造函数:
1. 调用对象时自动调用构造函数,只会调用一次,有参数可发生重载,可有多个构造函数
析构函数:
1. 无参数不可发生重载,只会调用一次
拷贝构造函数:
1. 把一个对象作为参数传递给另一个对象,调用构造函数,拷贝这个对象的所有成员
只要创建类就会给每个类添加至少三个函数
利用编译器提供的拷贝构造函数,会做浅拷贝操作,带来的问题是内存重复释放,程序崩溃(解决:自己实现拷贝构造函数)
operator:运算符重载-->对象之间相加
1. 重载的实质就是函数重载,运算符重载实现不同类型的数据加减
2. 不可以发生重载的运算符:访问类的成员运算符(.),域运算符(::),问号表达式( ? : ),sizeof
3. 重载运算符不能创建新的运算符,成员函数和友元函数,非成员非友元的普通函数也可重载运算符(全部)
4. 返回值、引用、默认参数等情况不可以发生函数重载
继承:
1. 公有继承一一对应,保护继承前二变保护,私有继承全部变私有
多态、虚函数:
1. 派生类和虚函数实现运行时的多态(动态多态),要满足有继承关系,子类重写父类的虚函数------virtual
2. 函数重载和运算符重载属于静态多态
3. 本质是通过父类来访问子类的方法,父类的成员函数必须是虚函数才构成多态
抽象类:
1. 虚函数后面加上“=0”的基类,唯一的作用是给派生类提供基类,不能被直接实例化
纯虚函数:
1. 虚函数等于0,凡是含有纯虚函数的类叫抽象类,子类必须完全实现基类的虚函数,不然也变成抽象类,不可直接实例化。
异常:
1. try{ } -------------- catch{ }
C++标准模板库STL:
1. 使用标准模板库来定义一个类,就不必手动创建类
2. 六大组件:容器、算法、迭代器、函数对象、适配器、分配器
3. 容器:vector(自动扩展,动态数组),list(无索引的双向队列),deque(可随机存取,两端插入删除的双端队列,但内存占用高)
GUI---人机交互图形化界面设计
对象树:简化内存回收机制
信号和槽:
1. connect(信号的发送者,发送的具体信号,信号的接收者,信号的处理)
2. 优点:松散耦合:发送端和接收端本身无关联,通过connet连接
3. 信号写在signal下,返回void,需要声明,不需要实现,可有参重载
4. 槽函数写在public slot或全局下,返回void ,需要声明和实现,可有参重载
5. 触发信号用emit,lambda表达式用来创建匿名的函数对象
对话框
1. 模态对话框:不可以对其他窗口进行操作,(非模态=可以操作)
案例:
1. 界面切换可以使用信号和槽,即其他界面emit发送一个信号,主界面接收
sqlite数据库:
1. sqlite3 数据库名.db---------.open-----------.quit---------creat,drop,insert,select