c++常见面试问题总结

c++和C语言的区别

C语言是面向结构性语言,C++是面向对象语言 c语言是c++的子集,c++包含了c语言的全部词法和语法内容,比c语言多出了类。

 

程序运行的保存的五个区

堆 栈 常量 全局变量 代码区

 

什么是面向对象:注重的是对象,当解决一个问题的时候,面向对象会把事务抽象成一个对象,就是说问题里有哪些对象,然后给对象赋一些属性和方法,然后让每个对象去执行自己的方法,最后解决问题

 

什么是面向结构:注重过程,当解决一个问题的时候,面向过程会把事情拆分成:一个个函数,然后按照一定的顺序执行完这些函数,然后把问题解决。

 

程序编译的几个步骤:

预处理:如头文件这些 输出i文件

编译:将文本文件.i 翻译成.s文件

汇编:  将文本文件.s翻译成机器语言 输出.o文件

链接:  将所有的.o文件处理合并 生成exe 可执行程序 被系统加载到内存里面

 

静态库  只生成lib文件

动态库的的写法  定义宏导出 ,把需要导出的方法前面加上预定义宏__ENTRY  

生成 lib 和dll

#ifndef __DLLEXPORT__

#define  __ENTRY__  extern "C" _declspec (dllimport)

#else   

#define  __ENTRY__  extern "C" _declspec (dllexport)

#endif

 

 

静态库和动态库的区别  

静态库是把运行程序所需的代码全部链接到exe文件中 成为exe的一部分 相对来说使用了静态库的程序 当多个程序调用相同的函数时,内存中存这个函数的多个拷贝,浪费宝贵的内存资源。

而动态库中exe仅仅包含了函数的描述信息,往往是一些重定位信息,仅当程序被装载到内存开始运行时,在window系统的管理下,才在应用程序与相应的dll之间建立链接关系,一般情况下 一个程序使用了dll  那么在内存中只有dll的一份复制品,由系统内存映射保证。

 

内存映射:dll首先被系统调入全局堆;栈,然后映射到调用这个dll的进程的地址空间,

在wind32系统中每个进程都有自己的地址空间。

 

库显示加载和隐式加载的区别

隐式加载:在编译前需要知道dll中具体有哪些函数,需要导入库文件

 

显示加载:在编译之前并不知道dll中的函数,而是在运行期间根据需要决定调用哪个函数,

通过调用loadLibrary获得dll的函数入口地址 在调用GetProcAdress获取函数的出口地址,然后通过函数返回的函数指针调用dll里面的函数,可以避免导入库文件

 

理解 线层同步  互斥的概念  区别:

所谓互斥就是指 多个线程通过竞争的方式进入进入临界区,在有限时间内,往往只允许单个用户访问,具体排他性,也没有顺序 。

 同步是指多个线程之间彼此合作,通过一定的逻辑关系共同完成一个任务,同步操作中往往包含互斥,同步也可以说是一中复杂的互斥。相当以一个线层的开始执行,依赖于另一个线层执行的进度。 比如一个线层要开始执行,需要另一个线层业务作为统治你,否则你就在那里等。

一台电脑最多能开启多少数量的线程:

一台电脑能开启的线程的数量 取决于进程调度策略,虚拟内存,硬件上主要是 物理内存、cpu   一般理论上上来说  线程的分析空间为一兆,一G内存大概是1024个

 

理解进程和线层的区别  

一个进程可以看做是一个独立的程序,有着自己的地址空间,一个进程下面可以有多个线层。

线层只能访问自己所属进程下的变量,而不能夸进程。

 

进程间的通信方式

管道  socket  共享内存  消息队列  信号量(用于控制进程间对共享内存资源的访问) 信号

 

事件  createEvent()分手动重置 自动重置 

mutex  createmutex();可以看成简易版的事件

临界区(用户去 非内核 速度最快,进程死锁问题)互相等问题 initialCriticalSection()

信号量  类似于车位  

Promise----futrue 同步  

 

网络七层 四层 模型的划分: 

七层: 物理层 数据链路层 网络层 传输层 会话层 表示层 应用层

四层:物理层 网络层 传输层 应用层

 

简述tcp的三次握手

 

为什么建立连接需要三次握手?

首先非常明确的是两次握手是最基本的。第一次握手,客户端发了个连接请求消息到服务端,服务端收到信息后知道自己与客户端是可以连接成功的,但此时客户端并不知道服务端是否已经接收到了它的请求,所以服务端接收到消息后的应答,客户端得到服务端的反馈后,才确定自己与服务端是可以连接上的,这就是第二次握手。

客户端只有确定了自己能与服务端连接上才能开始发数据。所以两次握手肯定是最基本的。

 

看到这里,你或许会问,那么为什么需要第三次握手呢?我们来看一下,假设一下如果没有第三次握手,而是两次握手后我们就认为连接成功了,那么会发生什么?第三次握手是为了防止已经失效的连接请求报文段突然又传到服务端,因而产生错误。

譬如发起请求遇到类似这样的情况:客户端发出去的第一个连接请求由于某些原因在网络节点中滞留了导致延迟,直到连接释放的某个时间点才到达服务端,这是一个早已失效的报文,但是此时服务端仍然认为这是客户端的建立连接请求第一次握手,于是服务端回应了客户端,第二次握手。

Connet  客户端请求连接  发送字段syn = 1

Accept    服务器确认接收客户端的连接 回复syn = 1 ack=1;

Write  客户端向服务器发送ack = 1 

四次挥手:

假设客户端先发起断连

客户端向服务器发送fin = 1 请求释放连接

服务器端收到后发送ack = 1

服务器向客户端发送释放连接请求 fin =1

客户端收到回复ack 等待2msl时间后关闭 服务器收到ack立刻关闭

 

Udp和tcp客户端其实都可以绑定自身的IP端口,而服务器必须绑定端口 IP

 

单播:服务器:1创建sosket   2.bind服务器IP端口,3.recvFrom

 

客户端:1.创建socket    

2. sockaddr_in addrto = { 0 };//客户端也可以bind绑定端口ip(指定某个端口发送)不绑定的话 系统默认分配一个,下面填的端口是服务器的端口 往哪里发得端口

  Addrto.sin_addr.S_un.S_addr = inet_addr(“192.168.0.1”) //发往的服务器Ip

  Addrto.sin_family = AF_INet;

  Addrto.sin_port = ::htons(30001); //和服务器一致的端口  要发往的端口                

sendto(sockClient,”hello”,6,reinterpret_cast<cosnst sockaddr>(&addrto),sizeof(addrto));

 

广播:服务器:1创建sosket   2.bind服务器IP端口3设置广播属性.BOOL ebnable =true;

 setSockopt(sockclient,SOL_SOCKET,SO_BRODCAST,reinterpret_cast<constchar*>(&enable),sizeof(eanable))   

  1. recvFrom接收   

 

客户端:1.创建socket()    

2. sockaddr_in addrto = { 0 };//客户端也可以bind绑定端口ip(指定某个端口发送)不绑定的话 系统默认分配一个,下面填的端口是服务器的端口 往哪里发得端口

 

  Addrto.sin_addr.S_un.S_addr = inet_addr(“192.168.0.1”) //发往的服务器广播的话也可以是192.168.0.255

  Addrto.sin_family = AF_INet;

 Addrto.sin_port = ::htons(30001); //和服务器一致的端口  如果服务器端设置了广播属性的话,客户端sendto255 所有服务器都可以收的到          

sendto(sockClient,”hello”,6,reinterpret_cast<cosnst sockaddr>(&addrto),sizeof(addrto));

 

组播:比广播更好控制发送给谁 有限定作用

组播和广播区别不大 区别在设置属性的函数

Ip_mreq mrq;

Mrq.imr_multiaddr.S_un.S_addr = ::inet(“224.0.0.2”)//s设置加入哪个组 定义组播号

Mrq.imr_interface.S_un._s_addr = 0;//使用默认网卡//

Setsockopt(socksever,IPPROTO_IP,IP_ADD_MEMBERSHIP,rinterpret_cast<const char*>(&mrq),sizeof(mrq));

客户端区别  sendto 往192.168.0.1发也可以 往服务器设置的组播地址发也可以。

 

Tcp和udp的区别:

TCP是流式、可靠的,面向连接的 相当与管道从一头流向另外一头 建立连接需要三次握手

UDP是面向非连接的,不可靠

Tcp是有序的 一对一  udp是无序的 可以一对多

Tcp效率较低,适用于准确性要求较高的场景

Udp效率较高,适用于实时通信。

 

static  const 类成员变量 成员方法  相关用法:  

static成员变量不属于类不占用类的空间大小,可以被一般类方法访问。static成员方法只能访问类的static成员变量和static方法。

const成员方法 方法后面加const 在const方法里面不能修任何改成员变量

const成员变量 初初始列表 const全局变量 定义的时候需要赋值

cosnt引用  目的是为了提高效率

 

智能能指针  

shared_ptr  

weak_ptr   用与观察shared_ptr当前装态 引用计数 是否释放 无效等    

unique_ptr;//禁止拷贝

 boost ::auto_ptr

scoped_prt;  //禁止转移所有权

 make_shared;   用于给shared_ptr 赋值  消除new和delete不平衡性质

 

stl 容器的迭代和删除

Map 红黑树实现  键值对

Set  集合  里面的元素对象不能重复

List  链表

Vector  动态数组

mutliSet  可重复集合

mutliLMap  一键对多值

仿函数: 就是一个类重载了()方法 看上去有点像函数

 

c++三大特性 :

继承 :子类继承基类  三种继承方式 -基类的私有成员 子类和外部都是不能访问的

封装:隐藏细节,private和protect变量 外部不可访问

多态:静态多态  重载

动态多态 虚函数  重写

虚函数表:指向 指针数组的指针  void(*a)[]

 

设计模式:

单例模式:

观察者模式:

适配器模式:

 工厂模式:

 

及不用虚函数实现c++多态的方式   通过类模板的方式 借助静态类型转换的方式  在基类里面讲将数接口在包一层。 WTL里面很多类似这样的做法

 

菱形继承 +virtual  

 

为什么类作为基类 析构函数最好是虚函数

Pbase * base = new child;  虚函数机制的话 根据实际对象调用析构函数;

Delete base;            不是虚函数机制的话,这样会调用基类的析构函数,而导致子类的无法释放

 

 

c++ 四种转换:

  dynaimc_cast    动态类型转换 鉴别真伪 条件:类 继承 virtual

  Base *pBase = new Base;

  Child *pChild = dynamic_cast<Child*>(pBase); //鉴别实际对象和实际类型是否一致 这里转换失败 : 下行转换

  Base *pBase = new Child ;

  Child *pChild = dynamic_cast<Child*>(pBase); //鉴别实际对象和实际类型是否一致 这里转换成功

 

  static_cast   静态类型转换       类 继承 可以基础类型之间转换如float转换成int  下行转换也是OK 用上面1的例子是可以转换成功的只看指针类型

  reinterpret_cast          无关系的类之间也可以,基础类型与类之间的转换,类型与c语言的强制转换

  const_cast<>       const 指针之间的转换

  

  int value1 = 1;

  int value2 = 2;

  const int* pvalue =&value1;   

  *pvalue = 9;   //错 指针常量 指向的值不让修改

   pvalue = &value2; //对

 

  int* const pvalue =&value1;

  *pvalue = 9;   //对

   pvalue = &value2; //错 常量指针 指针不让修改

 

const int* const pvalue =&value1;   

  *const_cast<int* const>(pvalue) = 9;  //去掉const 可以修改

 

 int* const pvalue =&value1;

 cosnt_const<const int *>(pvalue) = &value2//去掉对应的const

 

memcpy 及带内存重叠的实现

 

右值引用 深拷贝 浅拷贝:

类构造函数

A() = deafault   用于类中自己定义了构造函数 仍需要默认构造函数的情况 不然A a 这样调用或报错  必须A a(3)这样传一个参数。

A() = delete   //相当于这个类不能用

A() = explicit  // 相当于这个类不能隐式的调用  不能 A a = 5;只能A a(5);

 

迭代器iterator和指针的区别

迭代器是一个函数 只是重载了* ->这些符号

 

widows窗口程序的几个步骤:  

创建窗口类  注册窗口register: 创建窗口  显示更新窗口   获取窗口消息getmessage() 获取后dispatch消息 调用窗口处理函数

动态类型  看实际对象类型

静态类型(不加virtual)看左侧指针类型:决定调用子类还是父类的方法 static下行转换也是OK的

 

回去验证 不存在虚函数 继承之间的重写  静态类型static_cast Base*pBase = new Base;

                                                          Child * pChild = static_cast<Child*>(pBase);

 pChild ->show()  看看是调用基类还是之类的方法 期望调用子类的方法  然后去掉子类重写的方法看看调用的是不是基类的方法

然后子类不重写 看看是不是会调用基类类型的方法

 

iocp完成端口

完成端口等于异步IO+线层池 1.先建立一个空的完成端口IOCP = WASCreateIoCompletePort(),2.创建一定数量的线程,3.在WSARecv(sockClinet,wsaBuf,1,&recvCount,&dwFalg,overlapped,nullptr),overlapped这里面需要创建事件overlapped.event = WASCreateEvent();之后,不同于重叠IO 不是通过getoverlapped获取结果,通过线层池唤醒线层对接受的数据进行相关的业务处理,再次调用WASCreateIoCompletePort((HANDLE)sockClient,IOCP,/*传入的参数,完成建*/,/线程的数量/)进行投递到完成端口的队列,申明线层函数,在线层函数等待一个完成端口的事件::GetQueuedCompletionStatus(iocp,totalRecvCount,/完成件/,overlapped,infinity),里面通过传入的完成建将wasbuff打印出来。

 

重叠端口:

WSARecv(sockClinet,wsaBuf,1,&recvCount,&dwFalg,overlapped,nullptr);/获取数据 GetOverlappedResult((HANDLE)sockclint),&overlapped,&recvCount,,true); 系统通知你的时候把输入操作已经帮你做了。

 

异步选择事件:

事件和套接字绑定HANDLE aSock[50];

 HANDLE aEvent[50];

aEvent[0] = WSACreateEvent(); 创建事件

accept和recv需要由事件来通知  通过asock = socksever ;  WASEventSelect(sockserver,aEvent,FD_ACCEPT)中相关参数设置 accepte和recv的方式 用 ireturn = WSAWaitFormutilpleEvent(iicurrentNUm,aEvent,false,INFINITY,0)等待相应的事件置位 返回值是绑定对应数组的下标 由下标判断是哪个事件置位 accept还是recv

 

异步选择消息模型:通过windows消息的机制触发 消息到了 肯定是有accept用户连接 或者recv到数据了

线层池:

  1. 创建一定数量线层  创建事件 用于控制线层的退出  初始化信号量  里面车位刚开始位满 控制活跃的线层属  初始化临界区 用于控制读取任务的互斥
  2.  线层函数里面一个大循环,WaitForSingleObject(ms_pThreadPool->m_hSemaphore, INFINITE);  等待信号量提升 在addtask的时候提升信号量的空位

boost库  字符算法、智能指针、

 

数据库:

Mysql:

Mysqld  --install  //数据库安装

Net start mysql //数据库服务启动

Net stop mysql //停止数据库服务

Mysqld  --remove  卸载数据库

 

Select database()  当前使用的数据库

Mysql -uroot   以管理员前线登录

Show tables  查看当前数据库有多少表

show databases  //查看当前数据库所有数据库

Use test   //使用哪个数据库

Show engines  查看数据使用的哪种引擎

当前主要使用较多的两种:1、myisan 2 innodb 支持事务

 

Drop table dd; //删表

 

数据类型  decimal(p,s)//小数类型 前面是整数+小数一共的位数,后面是小数的位数

 

Crate datebase yy  建立数据库yy

 

//查看建立数据库语句

 Show create databse  ‘db’;

 

//建立一张表 id不能为负 可以null填充 不足六个整数前面用0填充 插入一条记录自增id

表尾 代表 引擎使用myisam 自增赋初值为5 编码格式使用gutf8

 Crate table dd(

 Id  INT(6) UNSIGNED  ZEROFILL  NOT NULL  AUTO_INCREMENT,

 Name VARCHAR(20) ,

 Sgender ENUM(‘男’,’女’,保密’’),

 PRIMARY_KEY(id)

)ENGINE=MYISAM  AUTO_INCREMENT =5  DEFAULT CHARSET = UTF8;

 

//查看表结构

//desc dd;

 

//修改表名:、

Rename table dd to student

 

//修改表中字段名及类型

Alter table dd change id tid int(8);

Alter table name sname varchar(30);

 

//给表增加一列

Alter table dd ADD score tinyint;

 

//在表中哪一列后增加一列

Alter table dd address varchar(80) after id;

 

//在表中删除某一列

Alter tabel dd drop COLUMN  address;

 

//插入

Insert  dd  valules(null,’李四’,’男’);

Insert  into dd values(null,’李四’,’男);

//插如多条记录

Insert  dd  valules(null,’李四’,’男’),Insert  into dd values(null,’李四’,’男);

//选择性插入

Insert dd(id,name) values(6,‘张三’);

//将表全部查出来在插入一遍

Insert into student(id,name,Sgender)select id name Sgender from dd;

 

 

//修改数据

Update student set Sgender = ‘男’ where name = ‘李四’

Update student set Sgender = ‘男’ ,id = 10 where name = ‘李四’

 

//删除数据

Delete from dd where id  = 8;

Delete form dd  //无条件删除所有记录

Delete from dd where name like ‘张’;删除姓张的

 

//查询

Select  * from dd

 

只显示姓名 成绩 以别名的形式

Select  name 姓名 ,id 学号 from student;

 

成绩小于八十的

Select *form student where score<80;

 

查询条件 between  and

Select * from student where score between 80 and 90;

 

基本条件like 条件%

查询姓名两个字的学生信息

Select *from student  where name like ‘__’;  两个下划线

Select *from student  where name like ‘张_’; 姓张的 名字两个字的

Select*from student where name ‘ %丽%’;名字有丽的  %代表一个和多个

 

基本条件查询 in() not in  多个范围

Select *from student where id in(8,9,10);

Select *from student where id not in(8,9,10);

 

基本条件运算 null  用is null 或 is not null

Select *from student where score is null

Update sutdent set scor = 0 where score is null;

 

分组查询  聚集 集合函数  主要配合分组  group by

 

Max()

Avg()

Count() 统计多少条记录

Sum()

Select avg(score) from student;

查询最高分

Select max(score) from student;

查询最高分学生的信息

Select *from student where score in(select max(score) from student);

统计多少人

Select cont(*)  from student

 

Select max(score)最高分, min(score) 最低分 from student;

 

查询各地区的人数

Select count(*) from student group by adress;

注意:在分组查询过程,只能出现聚集函数和分组字段 下面:

Select count(*) 人数,address 地区 from student group by adress  对

Select count(*) 人数,address 地区 , sname  姓名 from student group by adress  错  出现了名字 不是分组字段

 

Select count(*) 人数,address 地区 from student

Where address is not null  --条件   分组前  成绩为空 不参加分组

group by adress       -- 分组字段

Order by count(*) DESC; --根据人数降序

 

 

 

分组条件 分完组后按条件查询 需要放在 group by 后面

Select count(*) 人数,address 地区 from student

Where address is not null  --条件   分组前  成绩为空 不参加分组

group by adress       -- 分组字段

Having count(*)>2   --  分组后条件  分组后人数大于2的地区

Order by count(*) DESC; --根据人数降序

 

连接查询

建立两个表一个学生 一个老师

学生表里面包含老师的ID

 

多表查询  公司不推荐

Select  s.name ,s.sgender* fronm s ,t where s.tid  = t.tid;

连接查询  join  left join rignt join

Select s.name s.sgender from s left join  t  on s.tid  = t.tid;

 

Mysql 的约束

主键约束  primary key

默认约束  defaut

非空约束 not null

外键越苏  foreign key reference仅支持引擎为INoodb

Create table t

(

Tid  int unsigned not null auto increment

Tname varchar(20)

Key(tname) --建立表的时候 同事建立索引 名字不能重复

Primary_key(tid)

)

 

Create table t

(

sid  int unsigned not null auto increment,

sname varchar(20),

Tid int unsigned ,

Primary_key(tid)

Constraint fk foreign key (tid) reference t(tid)--建立外键 关联到teacher表

)

由于存在外键 删除某一项老师记录需要对应的学生不存在,删除老师表之前需要删除学生表 不然不让删除老师表  解决方案如下  级联删除

Create table t

(

sid  int unsigned not null auto increment,

sname varchar(20),

Tid int unsigned ,

Primary_key(tid)

Constraint fk foreign key (tid) reference t(tid) on delete cascade

)

加上on delete casecade 就能删除教师记录  但是还是不能删除教师表 除非先删除学生表

 

主键 不能为空 ,不能重复

外键  一遍一个表的外键指向 另外一个表的主键 且类型一致

增加一个表的主键()

alter table tt add constranit pk primary key(name);

增加一个表主键

Alter table tt drop primary key  

建立索引 方便检索数据  类似于书籍的目录  建立主键的时候 主键就是一个索引

Create index iia on(tname desc);

Alter table tt add index (tname desc);

 

删除索引

Drop index iia on teacher;

Alter table tt drop index tname;

 

常用函数:

Select length(‘ghh’);长度

Select * from student where sname like ‘__’;

Select *from student where char_lenth(sname) = 2;

 

//随机查询出两条记录

Select *from student order by rand() limit 

查询天前的日期

Selet date_add(now(),interval -10 day);

 

查询10后的日期

Selet date_add(now(),interval 10 day);

 

存储过程 

没有明确的返回值 编译后再服务器执行 熟读快

经过编译后存储在数据库中,用户通过 存储过程名字,并给出参数来执行它

函数 函数有返回值

 

Map 红黑树实现  键值对

Set  集合  里面的元素对象不能重复

List  链表

Vector  动态数组

mutliSet  可重复集合

mutliLMap  一键对多值

仿函数: 就是一个类重载了()方法 看上去有点像函数

c++三大特性 :

继承 :子类继承基类  三种继承方式

封装:隐藏细节,private和protect变量 外部不可访问

多态:静态多态  重载

动态多态 虚函数  重写

 

虚函数表:指向 指针数组的指针  void(*a)[]

 

设计模式:

单例模式:

观察者模式:

适配器模式:

 工厂模式:

 

及不用虚函数实现c++多态的方式   通过类模板的方式 借助静态类型转换的方式  在基类里面讲将数接口在包一层。 WTL里面很多类似这样的做法

 

菱形继承 +virtual  

 

为什么类作为基类 析构函数最好是虚函数

Pbase * base = new child;  虚函数机制的话 根据实际对象调用析构函数;

Delete base;            不是虚函数机制的话,这样会调用基类的析构函数,而导致子类的无法释放

 

 

c++ 四种转换:

  dynaimc_cast    动态类型转换 鉴别真伪 条件:类 继承 virtual

  

  Base *pBase = new Base;

  Child *pChild = dynamic_cast<Child*>(pBase); //鉴别实际对象和实际类型是否一致 这里转换失败 : 下行转换

 

  Base *pBase = new Child ;

  Child *pChild = dynamic_cast<Child*>(pBase); //鉴别实际对象和实际类型是否一致 这里转换成功

 

 

 

  static_cast   静态类型转换       类 继承 可以基础类型之间转换如float转换成int  下行转换也是OK 用上面1的例子是可以转换成功的只看指针类型

  reinterpret_cast          无关系的类之间也可以,基础类型与类之间的转换,类型与c语言的强制转换

  const_cast<>       const 指针之间的转换

  

  int value1 = 1;

  int value2 = 2;

  const int* pvalue =&value1;   

  *pvalue = 9;   //错 指针常量 指向的值不让修改

   pvalue = &value2; //对

 

  int* const pvalue =&value1;

  *pvalue = 9;   //对

   pvalue = &value2; //错 常量指针 指针不让修改

 

const int* const pvalue =&value1;   

  *const_cast<int* const>(pvalue) = 9;  //去掉const 可以修改

 

 int* const pvalue =&value1;

 cosnt_const<const int *>(pvalue) = &value2//去掉对应的const

 

memcpy 及带内存重叠的实现

 

右值引用 深拷贝 浅拷贝:

 

类构造函数

A() = deafault   用于类中自己定义了构造函数 仍需要默认构造函数的情况 不然A a 这样调用或报错  必须A a(3)这样传一个参数。

A() = delete   //相当于这个类不能用

A() = explicit  // 相当于这个类不能隐式的调用  不能 A a = 5;只能A a(5);

 

迭代器iterator和指针的区别

迭代器是一个函数 只是重载了* ->这些符号

 

 

 

widows窗口程序的几个步骤:  

 

创建窗口类  注册窗口register: 创建窗口  显示更新窗口   获取窗口消息getmessage() 获取后dispatch消息 调用窗口处理函数

 

动态类型  看实际对象类型

静态类型(不加virtual)看左侧指针类型:决定调用子类还是父类的方法 static下行转换也是OK的

 

回去验证 不存在虚函数 继承之间的重写  静态类型static_cast Base*pBase = new Base;

                                                          Child * pChild = static_cast<Child*>(pBase);

 pChild ->show()  看看是调用基类还是之类的方法 期望调用子类的方法  然后去掉子类重写的方法看看调用的是不是基类的方法

然后子类不重写 看看是不是会调用基类类型的方法

 

iocp完成端口 完成端口等于异步IO+线层池 1.先建立一个空的完成端口IOCP = WASCreateIoCompletePort(),2.创建一定数量的线程,3.在WSARecv(sockClinet,wsaBuf,1,&recvCount,&dwFalg,overlapped,nullptr),overlapped这里面需要创建事件overlapped.event = WASCreateEvent();之后,不同于重叠IO 不是通过getoverlapped获取结果,通过线层池唤醒线层对接受的数据进行相关的业务处理,再次调用WASCreateIoCompletePort((HANDLE)sockClient,IOCP,/*传入的参数,完成建*/,/线程的数量/)进行投递到完成端口的队列,申明线层函数,在线层函数等待一个完成端口的事件::GetQueuedCompletionStatus(iocp,totalRecvCount,/完成件/,overlapped,infinity),里面通过传入的完成建将wasbuff打印出来。

 

重叠端口:WSARecv(sockClinet,wsaBuf,1,&recvCount,&dwFalg,overlapped,nullptr);/获取数据 GetOverlappedResult((HANDLE)sockclint),&overlapped,&recvCount,,true); 系统通知你的时候把输入操作已经帮你做了。

 

异步选择事件:事件和套接字绑定HANDLE aSock[50];

 HANDLE aEvent[50];

aEvent[0] = WSACreateEvent(); 创建事件

accept和recv需要由事件来通知  通过asock = socksever ;  WASEventSelect(sockserver,aEvent,FD_ACCEPT)中相关参数设置 accepte和recv的方式 用 ireturn = WSAWaitFormutilpleEvent(iicurrentNUm,aEvent,false,INFINITY,0)等待相应的事件置位 返回值是绑定对应数组的下标 由下标判断是哪个事件置位 accept还是recv

 

 

异步选择消息模型:通过windows消息的机制触发 消息到了 肯定是有accept用户连接 或者recv到数据了

 

线层池:

  1. 创建一定数量线层  创建事件 用于控制线层的退出  初始化信号量  里面车位刚开始位满 控制活跃的线层属  初始化临界区 用于控制读取任务的互斥
  2.  线层函数里面一个大循环,WaitForSingleObject(ms_pThreadPool->m_hSemaphore, INFINITE);  等待信号量提升 在addtask的时候提升信号量的空位

 

boost库  字符算法、智能指针、

 

 

数据库:

Mysql:

 

Mysqld  --install  //数据库安装

Net start mysql //数据库服务启动

Net stop mysql //停止数据库服务

Mysqld  --remove  卸载数据库

 

Select database()  当前使用的数据库

Mysql -uroot   以管理员前线登录

Show tables  查看当前数据库有多少表

show databases  //查看当前数据库所有数据库

Use test   //使用哪个数据库

Show engines  查看数据使用的哪种引擎

当前主要使用较多的两种:1、myisan 2 innodb 支持事务

 

Drop table dd; //删表

 

数据类型  decimal(p,s)//小数类型 前面是整数+小数一共的位数,后面是小数的位数

 

Crate datebase yy  建立数据库yy

 

//查看建立数据库语句

 Show create databse  ‘db’;

 

//建立一张表 id不能为负 可以null填充 不足六个整数前面用0填充 插入一条记录自增id

表尾 代表 引擎使用myisam 自增赋初值为5 编码格式使用gutf8

 Crate table dd(

 Id  INT(6) UNSIGNED  ZEROFILL  NOT NULL  AUTO_INCREMENT,

 Name VARCHAR(20) ,

 Sgender ENUM(‘男’,’女’,保密’’),

 PRIMARY_KEY(id)

)ENGINE=MYISAM  AUTO_INCREMENT =5  DEFAULT CHARSET = UTF8;

 

//查看表结构

//desc dd;

 

//修改表名:、

Rename table dd to student

 

//修改表中字段名及类型

Alter table dd change id tid int(8);

Alter table name sname varchar(30);

 

//给表增加一列

Alter table dd ADD score tinyint;

 

//在表中哪一列后增加一列

Alter table dd address varchar(80) after id;

 

//在表中删除某一列

Alter tabel dd drop COLUMN  address;

 

//插入

Insert  dd  valules(null,’李四’,’男’);

Insert  into dd values(null,’李四’,’男);

//插如多条记录

Insert  dd  valules(null,’李四’,’男’),Insert  into dd values(null,’李四’,’男);

//选择性插入

Insert dd(id,name) values(6,‘张三’);

//将表全部查出来在插入一遍

Insert into student(id,name,Sgender)select id name Sgender from dd;

 

 

//修改数据

Update student set Sgender = ‘男’ where name = ‘李四’

Update student set Sgender = ‘男’ ,id = 10 where name = ‘李四’

 

//删除数据

Delete from dd where id  = 8;

Delete form dd  //无条件删除所有记录

Delete from dd where name like ‘张’;删除姓张的

 

//查询

Select  * from dd

 

只显示姓名 成绩 以别名的形式

Select  name 姓名 ,id 学号 from student;

 

成绩小于八十的

Select *form student where score<80;

 

查询条件 between  and

Select * from student where score between 80 and 90;

 

基本条件like 条件%

查询姓名两个字的学生信息

Select *from student  where name like ‘__’;  两个下划线

Select *from student  where name like ‘张_’; 姓张的 名字两个字的

Select*from student where name ‘ %丽%’;名字有丽的  %代表一个和多个

 

基本条件查询 in() not in  多个范围

Select *from student where id in(8,9,10);

Select *from student where id not in(8,9,10);

 

基本条件运算 null  用is null 或 is not null

Select *from student where score is null

Update sutdent set scor = 0 where score is null;

 

分组查询  聚集 集合函数  主要配合分组  group by

 

Max()

Avg()

Count() 统计多少条记录

Sum()

Select avg(score) from student;

查询最高分

Select max(score) from student;

查询最高分学生的信息

Select *from student where score in(select max(score) from student);

统计多少人

 

Select cont(*)  from student

 

Select max(score)最高分, min(score) 最低分 from student;

 

查询各地区的人数

Select count(*) from student group by adress;

注意:在分组查询过程,只能出现聚集函数和分组字段 下面:

Select count(*) 人数,address 地区 from student group by adress  对

Select count(*) 人数,address 地区 , sname  姓名 from student group by adress  错  出现了名字 不是分组字段

 

Select count(*) 人数,address 地区 from student

Where address is not null  --条件   分组前  成绩为空 不参加分组

group by adress       -- 分组字段

Order by count(*) DESC; --根据人数降序

 

 

 

分组条件 分完组后按条件查询 需要放在 group by 后面

Select count(*) 人数,address 地区 from student

Where address is not null  --条件   分组前  成绩为空 不参加分组

group by adress       -- 分组字段

Having count(*)>2   --  分组后条件  分组后人数大于2的地区

Order by count(*) DESC; --根据人数降序

 

连接查询

建立两个表一个学生 一个老师

学生表里面包含老师的ID

 

多表查询  公司不推荐

Select  s.name ,s.sgender* fronm s ,t where s.tid  = t.tid;

连接查询  join  left join rignt join

Select s.name s.sgender from s left join  t  on s.tid  = t.tid;

 

 

Mysql 的约束

主键约束  primary key

默认约束  defaut

非空约束 not null

外键越苏  foreign key reference仅支持引擎为INoodb

Create table t

(

Tid  int unsigned not null auto increment

Tname varchar(20)

Key(tname) --建立表的时候 同事建立索引 名字不能重复

Primary_key(tid)

)

 

Create table t

(

sid  int unsigned not null auto increment,

sname varchar(20),

Tid int unsigned ,

Primary_key(tid)

Constraint fk foreign key (tid) reference t(tid)--建立外键 关联到teacher表

)

由于存在外键 删除某一项老师记录需要对应的学生不存在,删除老师表之前需要删除学生表 不然不让删除老师表  解决方案如下  级联删除

Create table t

(

sid  int unsigned not null auto increment,

sname varchar(20),

Tid int unsigned ,

Primary_key(tid)

Constraint fk foreign key (tid) reference t(tid) on delete cascade

)

加上on delete casecade 就能删除教师记录  但是还是不能删除教师表 除非先删除学生表

 

 

主键 不能为空 ,不能重复

外键  一遍一个表的外键指向 另外一个表的主键 且类型一致

 

增加一个表的主键()

alter table tt add constranit pk primary key(name);

 

增加一个表主键

Alter table tt drop primary key  

 

建立索引 方便检索数据  类似于书籍的目录  建立主键的时候 主键就是一个索引

Create index iia on(tname desc);

Alter table tt add index (tname desc);

 

删除索引

Drop index iia on teacher;

Alter table tt drop index tname;

 

常用函数:

Select length(‘ghh’);长度

Select * from student where sname like ‘__’;

Select *from student where char_lenth(sname) = 2;

 

//随机查询出两条记录

Select *from student order by rand() limit 

查询天前的日期

Selet date_add(now(),interval -10 day);

 

查询10后的日期

Selet date_add(now(),interval 10 day);

 

存储过程 

没有明确的返回值 编译后再服务器执行 熟读快

经过编译后存储在数据库中,用户通过 存储过程名字,并给出参数来执行它

函数 函数有返回值

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值