游戏开发岗面经总结5(面相对象和面相过程的区别,多态,CG,设计模式,进程线程协程,动静态合批态,内存区域存放,指针和引用的区别,防止对象被拷贝,map和unordered_map)

Posted 头号理想

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了游戏开发岗面经总结5(面相对象和面相过程的区别,多态,CG,设计模式,进程线程协程,动静态合批态,内存区域存放,指针和引用的区别,防止对象被拷贝,map和unordered_map)相关的知识,希望对你有一定的参考价值。

我发现真的是好多东西 脑子里知道这个东西的大致,但是如果让你说出来 真的半句话憋不出来
所以我们还是得脚踏实地的一个问题一个问题的看 不能好高骛远

面相对象和面相过程的区别

1.面相过程是以过程为中心的编程思想,面相对象是以对象为基本程序结构单位的程序语言
2.面相过程是分析出解决问题的步骤,然后一步一步实现,一次一次调用
面相对象是对象具有唯一的静态类型,和有可能的多个动态类型,共享数据和操作
3.面相过程不支持面相对象的特性(多态,继承) 不允许混合持久化状态和逻辑
面相对象 在内部被表示为一个指针,任何对这个对象的操作 都是通过这个指针操作对象的属性和方法的

举个例子
女娲造人的时候, 人应该有一些特征:器官,大脑,四肢等这些就是抽象
如果有一天女娲的朋友想要知道造人的方法 但是女娲有很自私 毕竟这是女娲独一门的技术
所以他和它的朋友说:你不用考虑那么多 只需要告诉我想要什么样的人就行了 这就是封装
然后女娲以之前创造的人为模板 之后创造的都有之前的特征 这就是继承
为了让我们的世界更加丰富多彩,每个人又是不一样的 所以这就是多态

多态是什么 怎么实现的

多态就是: 父类型的引用指向子类型的对象
通俗版: 同一操作作用于不同的对象,产生不同的效果

好处: 1.提高程序的复用性(修改父类可以使得派生类发生改变)
2.提高扩充性和可维护性(派生类的功能可以被基类调用)

怎么实现的?
在基类的函数前加上virtual关键字,派生类中重写该函数,运行时将会根据对象的实际类型来调用函数
如果对象时派生类,就用派生类的函数,如果是基类 就用基类的函数

c++中多态分为两种,运行时多态和编译时多态
运行时多态:继承和虚函数实现
编译时多条:函数重载,运算符重载

GC

GC 就是垃圾回收器
作用:
1.提高软件开发抽象度
2.程序员可以不用费心在内存管理的问题上
3.使得模块之间更加清晰,减少耦合性
4.减少认为处理不当造成的 bug
5.内存使用更加高效

常见的设计模式以及应用场景

单例模式

单例模式是一种常用的设计模式
它的核心结构质保含一个被称为单例类的特殊类,通过单例模式可以保证系统中有一个类只有一个实例
而且该实例易于外界访问,从而方便对这个实例的控制,从而控制并节约资源

场景 :如果希望系统中某个类的对象只存在一个,单例模式就是很好的解决方案
举例
比如游戏中的UI控制器,音频管理器,特效管理器等等Manager均可使用单例模式

工厂模式

工厂模式就是主要为创建对象提供接口

场景: 在编码时不能预见需要创建哪种类的实例
系统不应该依赖于产品类实例如何被创建,组合和表达的细节

策略模式

定义了算法族,分别封装起来,让他们之间可以相互替换,此模式的算法的变化独立于使用算法的客户

场景:
一件事情,有很多方案可以实现
我可以在任何时候决定采用哪一种方式实现
未来可能增加很多的方案
策略模式可以让方案的变化不会影响到使用方案的客户

观察者模式

又称发布/订阅模式 定义了对象间一对多依赖
当一个对象发生改变的时候,所有依赖者的状态都会收到通知,并自动更新

场景

对一个对象状态的更新,需要其他对象同步更新,而且其他对象的数量动态可变
对象仅需要将自己的更新通知给其他对象而不需要知道其他对象的细节

举例
比如一个FPS游戏中可以设置不同的难度
每当手动选择难度(被观察的对象)之后动态更新BGM,关卡地图,怪物移动速度,攻击力等等参数

对于我们一般的想法可能是创建好多个不同的场景 然后根据UI加载 这样的话 很容易可以想到造成不必要的资源浪费

迭代器模式

提供一种方法顺序访问一个聚合对象的各个元素,而不暴露该对象的内部表示

场景

当你需要访问一个聚合对象的时候,不管这些对象是什么都需要遍历的时候,就用那个该考虑迭代器模式
stl容器就是很好的迭代器模式的例子

进程,线程,协程的区别

进程:拥有自己独立的堆栈,既不共享栈,也不共享堆,由操作系统调度
线程:拥有自己独立的栈,共享的堆,由操作系统调度
协程:同线程一样共享堆,独立的栈,由程序员手动调度协程

一个应用程序一般有一个主线程,多个辅助线程,线程之间是平行运行的,线程里面可以开启协程,让程序在特定的时间运行

进程和线程区别
1.进程是资源分配的最小单位,线程是程序执行的最小单位
2.进程有独立空间,线程没有,进程的资源独立,线程是共享的
3.进程执行开销大,线程执行开销小
4.进程是操作系统分配的基本单位,线程是处理机调度的基本单位

协程和线程的区别:
协程避免了无意义的调度,由此可以提高性能,程序员必须自己承担调度的责任,
同时线程失去了标准线程的多CPU的能力
线程是抢断式的,操作系统会中断当前进行的线程,将CPU控制权交给其他线程
进程是非抢断式的,需要主动调用yield来释放CPU控制权,不会被系统打断

协程的原理

unity在运行的时候,调用协程就是开启一个IEnumerator(迭代器),协程开始执行,
执行到yield return 之前协程和其他正常的应用程序没有任何差别,但是遇到yield return 之后就会立刻返回
并且将该函数暂时挂起,在下一帧遇到FixedUpdate或者Update之后判断yield return 条件是否满足
如果满足 则向下执行,否则继续挂起

unity中执行协程过程中,通过yield return xxx,将程序挂起,执行接下来的内容,
注意协程不是线程,在遇到yield return xxx 之前,协程方法和一般的方法是相同的,也就是程序执行遇到yield return xxx 之后
才会执行startcontinue()方法之后的程序,走的还是单线程模式,仅仅是将yield return xxx 之后的内容暂时挂起,等到特定的时间执行

函数的本质是压栈,协程的唤醒也是一样
调用的时候将其压入栈中执行,遇到yield return的时候就从栈中弹出

协程作用:
unity的核心逻辑是单线程,为了开发便利,统一生命周期的管理,不需要考虑锁的问题
一些操作非常耗时,比如资源加载等,如果让用户使用多线程开发,会十分复杂
unity在底层通过多线程完成,协程不断访问这个操作的状态判断加载是否完成

自写协程
核心内容就是两个列表
一个存放所有协程 一个存放挂起的协程
在每帧中检测挂起的条件是否符合如果符合继续挂起 否则开始执行

动态合批,静态合批

动态合批:
unity自带动态合批,需要在unity中开启 会导致CPU的消耗
限制:
物体的transform必须由相同的缩放系数
使用相同材质
一起逐个渲染
静态合批
unity中把物体标记为static 然后开启静态合批
限制:
需要保持static 不能改变transform
使用相同材质的物体才能合批
一个批次上线为~15K个顶点

内存区域有哪几块,分别存放了什么东西

内存区域共有五块:
1.栈区:主要是编译器自动分配释放,存放函数的参数值,局部变量,操作方式类似于数据结构中的栈
2.堆区:由程序员分配释放,存放new或者malloc出来的实例 由程序员负责释放(分配方式类似链表)
3.全局区(静态区):全局变量和静态变量存放在一起,初始化全局变量和静态变量放在RW
未初始化的全局变量和静态变量在ZI 程序结束后自动释放
4.文字常量区 :存放常量字符串,程序结束后自动释放
5.程序代码区:存放二进制代码

static全局变量和全局变量的区别

1.两者的存储区相同 都是全局区(静态区)
2.普通的全局变量作用整个源程序,如果一个源程序有多个源文件,那这个全局变量对所有源文件都有效
3.static全局变量限制了它的作用域只能在该变量定义的源文件内,只能此文件的函数使用,其他源文件不能使用这个static的变量

指针和引用的区别

1.引用必须被初始化,但是不分配存储空间
指针不在声明时初始化,在初始化的时候需要分配存储空间

2.指针是一个实体,引用只是一个别名
3.引用不能为空,指针可以为空
4.引用只能在定义的时候被初始化一次,之后不可变,指针可变(引用从一而终)
5.引用使用的时候无需解引用,指针需要解引用

防止对象被拷贝

把拷贝构造函数和operator=都在private里声明

map和unordered_map的区别

map内部实现使用红黑树(非常严格的二叉平衡排序树)具有自动排序功能
所以map中所有的元素都是排序好的 因此map进行的查找删除添加等操作相当于对二叉树进行操作

unordered_map内部实现使用哈希表,元素是无序的

map优点:有序性,效率高(由于红黑树的缘故)
缺点:空间占用高,红黑树每个节点都要保存父节点 孩子节点和红黑性质 占用大量的空间

unordered_map 优点:查找速度快(哈希表)
缺点:建立哈希表比较浪费时间

对于查找问题unordered_map比较适合,遇到对顺序有要求的适合使用map

以上是关于游戏开发岗面经总结5(面相对象和面相过程的区别,多态,CG,设计模式,进程线程协程,动静态合批态,内存区域存放,指针和引用的区别,防止对象被拷贝,map和unordered_map)的主要内容,如果未能解决你的问题,请参考以下文章

游戏开发岗面经总结4(DrawCall,c++11新特性)

游戏开发岗面经总结7(函数调用底层,值捕获和引用捕获,宏定义和内联,排序算法稳定性,static,软工思想,sprite和image的区别,细小物体碰撞问题)

游戏开发岗面经总结7(函数调用底层,值捕获和引用捕获,宏定义和内联,排序算法稳定性,static,软工思想,sprite和image的区别,细小物体碰撞问题)

从面相对象的学习过程中得出的程序开发者需要具备的类比学习能力

Python面向对象编程总结(上)

python面相对象进阶