C/C++/嵌入式学习笔记

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值