C++面经知识点

面对对象
1.面向对象是一种编程思想,把一切东西看成是一个个对象,比如人、耳机、鼠标、水杯等,他们各自都有属性,比如:耳机是白色的,鼠标是黑色的,水杯是圆柱形的等等,把这些对象拥有的属性变量和操作这些属性变量的函数/方法打包成一个类来表示
2.面向过程和面向对象的区别
面向过程:根据业务逻辑从上到下写代码
面向对象:将数据与函数绑定到一起,进行封装,这样能够更快速的开发程序,减少了重复代码的重写过程

C++五大特性:对象、抽象、封装与消息隐藏、继承、多态

三大特性:封装、继承、多态

封装:将代码的细节隐藏起来,然后对外界提供可以使用的公共方法。
在现实生活中,一台电饭煲,一台榨汁机都是封装的体现,榨汁机只需要我们加入材料按下按钮,就能为我们榨一杯果汁,我们不知道榨汁机内部的运行细节,但是它给了我们想要的结果。public、protected、private

继承:继承就是子类继承父类的属性特征和行为方法,使得子类对象(实例)具有父类的变量和方法,使得子类具有父类相同的行为。子类能对父类方法进行重写overrride

面对对象六大基本原则:单一职责原则、开闭式原则、迪米特原则、里氏替换原则、依赖倒置原则以及接口隔离原则

函数重载与函数模板
函数模板,其函数的类型和形参的类型不具体指定,凡是函数体相同,在模板中定义一次就行了。
函数重载:在同一作用域内(同一类里面),一组具有相同函数名、不同形参列表的函数,每个函数都要定义。
相对于函数重载而言,模板具有得天独厚的优势,它不需要重复定义,所以使用起来比函数重载更简洁,但函数模板只适用于函数的参数个数相同而类型不同,且函数体相同的情况,如果参数的个数不同或函数体不同,只用函数重载,这就是函数模板相对于函数重载的缺陷。

多态
在现实生活中,多态是同一事物在不同场景下的多种形态。
在面对对象中,多态是指通过基类的指针或引用调用虚函数,在运行时动态调用实际绑定对象的行为。与之对应:编译时绑定函数是静态绑定。
在这里插入图片描述

为什么使用多态:有公共特性(基类)还要有自己的特性(子类),用于区别不同特征。增加程序接口的可扩展性,即需要修改或增加程序功能时改动的代码较少。

虚函数表:每一个有虚函数的类(基类和派生类)都一张虚函数表(编译时生成、运行时载入内存)存放虚函数地址,该类的任何对象都存放着指向该表的指针。通过基类的指针或引用指向或绑定的对象找到对应虚函数表,查找应当执行的虚函数版本。

虚函数与纯虚函数:有时候基类生成对象是不合理的,比如动物(抽象类)-老虎、狮子,所以这种基类不实例化,子类再实例化。
1.虚函数和纯虚函数可以定义在同一个类中,含有纯虚函数的类被称为抽象类,抽象类无法实例化,而只含有虚函数的类不能被称为抽象类。
2.虚函数可以在父类被直接调用,也可以被子类重载以后以多态的形式调用,而纯虚函数必须在子类中实现该函数才可以使用,因为纯虚函数在基类只有声明而没有定义。

基类A与派生类B的sizeof:其实是对象所占字节点数,主要是类的非静态成员变量及编译器额外增加的变量大小(静态成员变量不在对象中存储),基类:sizeof(A),派生类sizeof(A)+sizeof(B),如果派生类有虚函数,还有加上指向虚函数表的指针sizeof(ptr)

多进程:QQ和微信一起使用。
多线程:多任务处理的一种特殊形式,允许让电脑同时运行两个或两个以上的程序。
多任务处理有两种形式:基于进程和基于线程。
基于进程的多任务处理是多个程序的并发执行(多进程)。
基于线程的多任务处理是同一程序的多个片段的并发执行(多线程)。

external:置于变量或者函数前,以标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义-全局有效。

const:(许多函数参数是只读不写的,函数体内不作修改)被编译器视作常量,其值不能改变,防止意外修改,增强程序的健壮性。编译器不为const常量分配存储空间,没有存储与读内存的操作,提高了效率。
1)阻止一个变量被改变;
2)声明常量指针和指针常量;
3)const修饰形参,表明它是一个输入参数,在函数内部不能改变这个形参;
4)const修饰类的成员函数,表明它是一个常函数,不能修改类的成员变量;
5)const修饰成员函数的返回值,以使得其返回值不为”左值”,右值是不变的。

const不能与static同时使用(静态成员函数不能声明为const),因为static修饰静态成员函数-不属于对象,不含this指针,即不能实例化,而const成员函数必须具体到某一实例,函数调用方式为this call。

static:静态成员是为了实现共享,静态成员属于类不属于对象,一个实例被多个对象共享。静态成员主要是为了方便调用,不需要生成对象就能调用静态成员。但是静态成员函数不存在this指针,不能访问非静态成员-只能访问静态成员变量(类变量)和函数。在类中声明static变量或者函数时,类外初始化时使用作用域运算符来标明它所属类,因此,静态数据成员是类的成员(类变量),而不是对象的成员(实例变量)。
1)函数体内的static变量的作用范围为该函数体 ;
2)模块内static全局变量和函数可以被模块内的函数访问,不能被模块外函数访问;
3)类中的static成员函数属于整个类所拥有,这个函数不接收this指针,因而只能访问类的static成员变量;
4)类中的static成员变量属于整个类所拥有,对类的所有对象只有一份拷贝;

this:是一个const指针,它指向当前对象并不改变指向,通过->可以访问当前对象的所有成员。所谓当前对象,是指正在使用的对象。例如对于stu.show();,stu 就是当前对象,this 就指向 stu。this 实际上是非静态成员函数的一个隐式形参,在调用成员函数时将对象的地址作为实参传递给 this。可以在需要返回类对象本身时使用return *this,可以用于区别同名的类成员变量和传递的参数,this->num = num,左边是成员变量,右边是函数传递的参数。

final关键字:不允许此类被继承。

容器:使用迭代器遍历
vector-类似于数组,连续内存,方便存取
list-类似于双向链表,通过指针访问,方便元素查找,内存不连续
deque-类似于双向vector,支持双端操作,是vector和list的折中
map-类似于数据库的键-值组合,通过键自动排序,键不重复存储-去重,红黑树实现
set-键和值合为一体,红黑树实现,方便元素查找

返回多个值:指针传参写数据或结构体。vector()!!!

指针和引用的区别
1)指针是一个变量,它存储的是一个地址,可以是空值并随时被初始化且可以改变;引用是变量的别名,对引用操作就是对变量本身操作,创建时必须初始化且不可变。
2)"sizeof引用"得到所指向的变量(对象)的大小, "sizeof指针"得到指针本身的大小。
3)指针可以有多级,但是引用只能是一级(int **p;合法 而 int &&a是不合法的)。
4)指针是拷贝,引用是绑定。

函数指针:(回调函数)指向函数的指针,绑定到函数。
指针函数:返回指针的函数。

智能指针:解决内存泄露,shared_ptr,引用计数指明对象被多少指针共享。

仿函数(函数对象):此类的对象可以像函数一样被调用,重载调用运算符(),比函数指针执行起来更快

Lambda表达式:是一种函数对象,需要传入更多参数时使用,未命名的内联函数。

指针数组和数组指针
指针数组:它是一个数组,数组的元素都是指针;
数组指针:它是一个指针,它指向一个数组。

值传递:形参是实参的拷贝,改变形参的值并不会影响外部实参的值;
指针传递:形参是指向实参的指针,对形参的指向操作时就相当于对实参本身进行操作,可以改变实参但指针本身没有变,所以仍然是拷贝;
引用传递:形参是实参的“别名”,对形参的操作其实就是对实参的操作,属于绑定。

模板:泛型编程/通用编程(不是具体类型)
模板定义:模板就是实现代码重用机制的一种工具,它可以实现类型参数化,即把类型定义为参数, 从而实现了真正的代码可重用性。(代码量大时比函数重载更有效)
模版可以分为两类,一个是函数模版,另外一个是类模版。

拷贝构造函数:基于同一类的一个对象去构造和初始化另一个对象(在内存中还不存在)。在C++中3种对象需要复制,此时拷贝构造函数会被调用:1.一个对象以值传递的方式传入函数体;2.一个对象以值传递的方式从函数返回;3.一个对象需要通过另一个对象进行初始化。
浅拷贝:如果复制的对象中引用了一个外部内容(例如分配在堆上的数据),那么在复制这个对象的时候,让新旧两个对象指向同一个外部内容,就是浅拷贝。(指针虽然复制了,但所指向的空间内容并没有复制,而是由两个对象共用)
深拷贝:如果在复制这个对象的时候为新对象制作了外部对象的独立复制,就是深拷贝。因为系统提供的默认拷贝构造函数工作方式是内存拷贝,也就是浅拷贝。如果对象中用到了需要手动释放的对象,则会出现问题,这时就要手动重载拷贝构造函数,实现深拷贝。

拷贝赋值函数:基于同一类的一个对象向另一个对象赋值(两个对象都已经存在)。
总之:
对象不存在,且没用别的对象来初始化,就是调用了构造函数;
对象不存在,且用别的对象来初始化,就是拷贝构造函数(上面说了三种用它的情况!)
对象存在,用别的对象来给它赋值,就是拷贝赋值函数。

C/C++程序的内存分配:栈、堆、全局/静态、常量、程序代码区

栈溢出和堆溢出:数组越界和野指针/忘记释放(内存泄露)

内存分布:(1GB+3GB)内核、栈区、缓冲区、堆区、静态全局区、只读常量区、代码区
内存分配方式:静态存储区、栈区、堆区
栈溢出:递归没有结束条件、向内存空间写入超出其本身长度的数据(数组、字符串)。
内存泄露(堆溢出):动态申请的空间使用后没有归还,解决:使用智能指针。
内存溢出:要求分配的内存空间超出系统所能提供的。
内存越界(栈溢出/缓冲区溢出):是指向系统申请一块内存后,使用时却超出申请范围。
异常处理:throw、try、catch
一个C++程序从写到执行的过程
预处理—编译—汇编—链接
hello.c-hello.s-hello.i-hello.o-可执行文件

malloc和new的区别
1)属性:new/delete是C++关键字-需编译器;malloc/free是C库函数-需头文件。
2)参数:使用new操作符时无须指定内存块的大小,编译器会根据类型信息自行计算。而malloc则需要显式地指出所需申请内存的尺寸。
3)返回类型:new操作符内存分配成功时,返回的是对象类型的指针,类型严格与对象匹配,无须进行类型转换,故new是符合类型安全性的操作符。而malloc内存分配成功则是返回void * ,需要通过强制类型转换将void*指针转换成我们需要的类型。
4)new/delete会调用构造、析构函数,malloc/free不会,所以他们无法满足动态对象的要求。

C和C++区别
1)C面向过程,C++面向对象。C是一个结构化语言,它的重点在于算法和数据结构。C程序的设计首要考虑的是如何通过一个过程,对输入进行运算处理得到输出(实现过程/事务控制);C++语言中有类、对象、继承、多态这样的OOP语言必备的内容,在设计大型软件是可以做到高内聚,低耦合,此外C++支持模板,运算符重载,异常处理机制,以及一个非常强大的C++标准模板库STL
2)关于动态内存管理,C语言通过malloc和free来进行堆内存的分配和释放,而C++是通过new和delete来管理堆内存的。
3)关于输入输出方式,C中printf/scanf是C的库函数,cout/cin是C++中ostream和istream类型的对象。
4)关于struct,在C++中,struct关键字不仅可以用来定义结构体,它也可以用来定义类(于C++中struct和class的区别)

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值