注:面试过程中整理的学习资料,如有侵权联系我即刻删除。
目录
cpp文件中经常都有#if #endif,这个的作用是什么呢?
#ifdef _DEBUG #define new DEBUG_NEW #endif 的作用是什么,cpp头经常包含?
const修饰this指针的时候,如cassA * const this;
不能同时用const和static修饰成员函数,virtua和static也不能同时修饰成员函数。
在c++程序中调用c语言编译的函数为什么要用extern c?
时间复杂度和空间复杂度,说一下各大排序的时间复杂度和空间复杂度
C++虚继承的概念
虚继承和虚函数是两个完全不相关的两个概念。
普通的多重继承,当两个或多个父类中包含有同名函数或者同名变量时,这时用子类构造的对象来调用这个同名函数就不行,会有二义性。
< 比如类B、C都继承于类A,然后类D继承于B,C,这时候用D的对象来调用同名函数就不行,就具有二义性。>
为了解决这个普通多重继承的二义性,继承的时候将共同基类设置为虚基类,继承的时候加。这时从不同的路径继承过来的同名数据成员在内存中就只有一个拷贝,同一个函数名也只有一个映射。这样不仅就解决了二义性问题,也节省了内存,避免了数据不一致的问题。
虚继承也会产生虚指针。每个虚继承的子类都有一个虚基类指针和虚基类表(不占用类对象的存储空间);当虚继承的子类被当做父类继承时,虚基类指针也会被继承,多继承的话会继承两个指针,D会继承两个指针,而同名数据成员只有一份。
C++如何实现接口?
抽象类可以作为接口。基类声明纯虚函数,每个派生类根据自己的特点重写纯虚函数,这样就可以获取同一接口的不同实现。
C++中如何传参?
- 值传递
值传递中,实参和形参是两个不同的地址空间,参数传递的实质是将原函数中变量的值,复制到被调用函数形参所在的存储空间中,这个形参的地址空间在函数执行完毕后,会被回收掉。整个被调用函数对形参的操作,只影响形参对应的地址空间,不影响原来函数中的变量的值,因为这两个不是同一个存储空间。
- 引用传递
引用就是变量的别名,对引用的操作就等价于对实参的操作。函数执行完后,会直接改变实参的值。
- 指针传递
实参是变量的地址,形参是指针,对指针变量的操作,就是对指向地址所对应的实参进行操作。
抽象类和接口的联系和区别?
在c++中,抽象类是包含了一个或者多个纯虚函数的类,是不能被实例化的类。在c++中,用抽象类来实现接口。
接口是java中的概念。
区别:
- 接口和抽象类的概念不一样。接口是对动作的抽象,抽象类是对根源的抽象。抽象类表示的是,这个对象是什么。接口表示的是,这个对象能做什么。
- 继承类对于抽象类所定义的抽象方法,可以不用重写,也就是说,可以延用抽象类的方法;而对于接口类所定义的方法或者属性来说,在继承类中必须要给出相应的方法和属性实现。
- 一个类一次可以实现若干个接口,但是只能扩展一个抽象类。
简述一下程序的编译链接过程
编译链接过程包括:预处理(预编译)、编译、汇编、链接。
预处理(预编译):主要是做一些代码文本的替换工作,展开所有的宏定义、处理条件编译、编译头文件等。
编译:把预处理完的文件做语法检查,对代码进行优化,将文本文件.i翻译成.s文件,得到汇编代码。
汇编:把.s文件(汇编代码)->机器指令(二进制代码),结果保存在目标文件.obj中。
链接:将多个目标文件、库打包到最终的可执行文件。
分为动态链接和静态链接。
静态库和动态库:
静态链接库和动态链接库都是共享代码的一种方式。
- 静态链接库是一组.obj文件的集合,不需要动态加载,已经固化在程序中,在编译时就打包进了可执行文件,这样程序在运行时候就不会再和静态库有任何关系,这样的好处是快,但是造成了空间的浪费,exe文件会很大。而动态链接库是动态加载dll的,在运行的时候再加载,不用一直占内存。
如果对静态库进行了更新,那么需要重新编译代码,并且提示用户进行下载整个软件,这样会造成很多不便。而动态链接库的话,只需要更新替换dll就行,维护很方便,但是缺点在于,如果dll丢失或者误删,程序就无法运行了。
怎么调用静态链接库和动态链接库
动态链接库和静态链接库的创建,是在建立工程的时候勾选的。再在项目属性中点击输出目录。
静态链接库的调用:
- 把.h文件加入工程中,在要调用此库的cpp文件中包含这个头文件。
- 然后在工程属性/VC++目录/库目录中添加.lib所在文件夹的路径。
- 在工程属性/链接器/输入/附加依赖库中添加此库的文件名(.lib),或者在调用此库的.cpp文件中添加#pragma comment(lib, “.lib”)。
动态链接库的调用:
- 除了包含头文件,库目录中添加.lib路径,链接器中添加.lib文件名,还要把.dll文件拷贝到工程的debug文件下。
VS的调试技巧:
a悬停鼠标查看变量值;
b调试时程序死锁或者死机,点击全部中断,调用堆栈看卡死的信息。
c调试的时候想改变一个变量的值来看发生什么情况,可以双击变量直接输入一个新值。
d设置断点调试时跑过了,可以直接拖动黄色箭头或者右击设置下一条语句,就到想要那句了。
运算符的优先顺序?
从高到低:
[ ](下标运算符)
!(判断运算符)
++ - -
*(指针) &(与) |(或) ~(取反) ^(亦或) (位操作)
+ - * / %(算术运算符)
< <= > >= == !=(关系运算符)
&& || !(逻辑非运算符)
表达式1 ? 表达式2 : 表达式3 (条件运算符,也就是三目运算符)
= (赋值运算符)
, (逗号运算符)
总之,初等运算符>单目运算符>算术运算符>关系运算符>逻辑运算符>赋值运算符>逗号运算符。
怎么判断大端小端模式?
小端模式是高字节放高地址,低字节放低地址。大端模式就是高字节放低地址,低字节放高地址。把一个int值赋值给char型变量,再打印char型变量的值,看看这个变量的值是int型的高字节还是低字节。比如 int a = 1;char b=a;打印b出来b是1,那就是小端模式,是0则是大端模式。
结构体和联合的区别?
联合中的变量都占用的同一个内存,各个变量不能同时存在。联合内存长度是联合中的最长的成员所占的内存长度,结构体的内存长度是变量所占内存长度