游戏研发 校招面经解读(一)

如何定义纯虚函数:

C++:在一个类里面定义纯虚函数: 在函数定义后面加上= 0;

并且这个类就变成了虚基类,无法实例化,就是不能创建对象,只能被继承,并且继承之后,子类必须实现纯虚函数。

抽象类是实现多态的一种途径。可以提高代码的可扩展性灵活性

可扩展性:对同一个接口想实现有区别的功能的时候,只需要继承抽象类实现一个新的接口就行了。

灵活性:灵活地编程。面向接口编程,只需要改接口的部分,不需要改其他地方,而且可以用抽象类的指针去指向其子类的对象,这样就实现了以统一的方式处理不同的子类对象

C#中没有像C++那样的纯虚函数的概念,但是依旧有抽象类和抽象方法

(abstract),不能实例化,方法不用实现public abstract void area();

C++ 和 C#的抽象类中都可以定义虚函数(非抽象方法),不用 =0 和 abstract,可以被继承,也可以被重写override

C#的抽象方法只能定义在抽象类里面吗?

    是的,因为不同的类不允许有没有实现的方法。

宏定义有哪些作用?

定义常量
定义函数
调试信息
#ifdef DEBUG
#define LOG(x) std::cout<<x<<std::endl;
#else
#define LOG(x) //空展开
#endif
条件编译:#ifdef #ifndef #elif
#if #elif
#endif
用宏define出来的常量和函数,在使用到它的时候会进行宏展开,其实就是文本
替换,但是,就是因为宏是文本替换,所以他是类型不安全的。比如,用一个宏
实现比较大小的功能,如果是int,double这样的数据类型,他就可以正常工
作,但是如果传进去了两个字符串(sring),那就不能正常工作了

不会被编译器检查出来的错误有哪些?

   要解决这种问题,可以用函数重载来实现,或者用模板来实现,对于
   string,可以用模板特化来实现,自定义的数据类型的话,可以使用操作符
   重载

条件编译和visual studio的debug模式, release模式有点像,比如说,我们可以预定义好一种LOG宏函数

   #ifdef DEBUG
   #define LOG(X) std::cout<<X<<std::endl;
   #endif

并且它只有DEBUG这个宏被定义的时候才会被编译。

并且在代码段里面,也是用条件编译,只有DEBUG这个宏被定义的时候,相关代码才会被执行

#ifdef DEBUG
Log(x);
#endif

C++是类型安全的编程语言:绝大部分类型相关的错误能够在编译期间被检查出来

C++编译器找不出来的错误:

数组越界:不管是[]还是vector,都无法在编译的时候找出越界问题

访问空指针:解引用空指针(nullptr)的时候

一个模板类有什么作用:

减少重复代码。模板类是编译时多态的一种体现,他把数据类型作为参数,在编译时对不同的数据类型生成特定的代码实现,能够减少重复代码的书写。像C++的STL容器就都是模板类

提高代码的灵活性和可扩展性:对某些特殊类型的实例化模板,我们可以进行模板特化,为它实现和模板类不同的功能。

增加类型安全。使用模板类,会在编译期间生成代码进行编译,同时会检查类型的正确性

提高性能,虽然会增加编译时间,但是比运行时再进行类型转换或者运行时多态快 C#的委托实际上是怎样的类型。

是一个特殊的类,是方法的容器,可以将任意个同类型的方法当作参数传递,存储和调用

C#的编译流程是怎样的

和C++很不一样。

先编译生成中间语言(IL),存储在.exe或者dll中, 

运行的时候,需要使用.NET框架,再经过一次JIT编译,.NET框架会根据不同的平台生成对应的机器码,这期间还会进行链接,优化等操作,并将程序载入内存

静态库和动态库有什么不一样呢

静态库会被拷贝至应用程序中,成为应用程序的一部分,因此调用它会更快,不过,当很多个程序都用到这个库的时候,内存中会出现很多个这个库的代码,浪费空间

动态库只有在用到它的时候才会被加载进内存,且内存中只会存在一个,允许多个程序共用这个库

C++ 动态库的代码是怎么被主程序执行的:

比如说,我现在要printf了,那么我就要用到CRT(C RunTime)这个动态链接库,它会被载入内存,但是我要怎么知道printf在哪里,我又要怎么读到CPU里面去并执行它呢?

当你的程序调用 CRT 中的 printf 函数时,操作系统会负责将 CRT 动态链接库加载到内存中。

在编译和链接过程中,链接器会将你的程序中对 printf 函数的调用解析为对 CRT 中 printf 函数在内存中地址的引用(这里是逻辑地址)。这样,在运行时,当你的程序调用 printf 函数时,它实际上是通过引用 CRT 中 printf 函数在内存中的地址来调用它的。

当你的程序运行时,操作系统会为它分配一个虚拟地址空间。虚拟地址空间中的每个虚拟地址都会通过内存管理单元(MMU)映射到物理内存中的一个物理地址。这个映射过程是由操作系统管理的,并且对你的程序是透明的。

因此,当你的程序调用 printf 函数时,它实际上是通过引用一个虚拟地址来调用它的。这个虚拟地址会被 MMU 映射到物理内存中“CRT 动态链接库”所在位置的一个物理地址。

这样,你的程序就能够通过引用这个虚拟地址来调用 CRT 中 printf 函数在内存中的实际位置。

操作系统会为每个进程创建页表,当进程被载入内存的时候,就会更新页表的内容

在用到了动态链接库的指令的时候,CPU会根据操作系统的MMU,访问到动态链接库所在的物理内存,取出相关的指令,便可以执行动态链接库的代码了(例如printf)

更多内容:

编程导航:编程导航 - 做您编程路上的导航员

知乎:小心摸鱼 - 知乎

bilibili:小心摸鱼的个人空间-小心摸鱼个人主页-哔哩哔哩视频

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值