c/c++ 面试笔试知识点----牛客网(3)

51. 
静态分配是指在编译阶段就能确定大小,由编译器进行分配,堆不可以进行静态分配,堆的申请都是在执行过程中进行的。
A,堆和栈的大小都可以设置,栈一般只有几KB。
B,堆在动态分配时,要申请连续的内存空间,释放后会产生碎片。
D,堆是使用malloc()、calloc()、realloc()等函数动态分配的,而使用alloca()函数可以动态分配栈的内存空间,释放的时候由编译器自己释放。
52. 
抽象类不能实例化, 因而D选项明显不正确。
抽象类不能参数类型和函数返回类型,因而A和C不对
抽象类可以用作指针类型,因而B选项正确
53.
  C语言中的标识符有:关键字、预定义标识符、用户标识符
54. 
理解函数返回变量,指针,数组;
当函数返回值之后,其函数内部的栈空间均会被销毁;
在函数内部,若程序员没有为指针分配空间,则函数退出时,其栈空间也就不存在了;
因此,使用数组时,不能返回一个数组;
55. 
重载多态和强制多态是 指 特定多态。
参数多态和包含多态是指 通用多态。
56. 
优先使用对象组合,而不是继承 ”是面向对象设计的第二原则。
组合也叫“对象持有”,就是在类中定义另一类型的成员, 继承会破坏类的独立性,增加系统的复杂性,一般系统的继承层次不超过3层。组合拥有良好的扩展性,支持动态组合,因此请优先考虑组合方法。
57. 
要想搞明白该问题,需要理解基类构造析构函数、子类构造析构函数和子类成员变量构造析构函数的调用顺序。
对于构造函数:基类构造函数 > 子类成员变量构造函数 > 子类构造函数
对于析构函数:子类析构函数 > 子类成员变量析构函数 > 基类析构函数
58. 
说一下虚函数:
1.  被virtual关键字修饰的成员函数,就是虚函数。虚函数的作用,用专业术语来解释就是实现多态性(Polymorphism),多态性是将接口与实现进行分离;用形象的语言来解释就是实现以共同的方法,但因个体差异而采用不同的策略。
2. C++中的虚函数的作用主要是实现了多态 的机制。关于多态,简而言之就是用父类型别的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数。这种技术可以让父类的指针有“多种形态”,这是一种泛型技术。 所谓泛型技术,说白了就是试图使用不变的代码来实现可变的算法。
59. 
后缀++ 和-- 操作符本质上比前缀一目操作的优先级高, 因此*p++ 和*(p++) 等价, 它自增p 并返回p 自增之前所指向的值。
要自增p 指向的值, 使用(*p)++, 如果副作用的顺序无关紧要也可以使用++*p。
60. 
只有类的非静态成员才有this指针,static显然没有,友元函数也没有
61. 
这么需要考虑虚函数表,指向虚函数表的指针在32位系统下占用4个字节,其地址分布在整个类成员变量的地址的首部,接下来就是变量a的地址、b的地址。当将test对象obj赋给指向整型的pInt后,指针pInt指向了地址的首部也就是虚函数表指针,所以*(pInt+0)=100改变的是虚函数表的值,接下来*(pInt+1)=200改变的是变量a的值,变量b没有变换。
62. 
C 语言中用 "%%" 打印输出字符 "%", 所以 %%d, 输出为 %d 两个普通字符 , 而不是格式控制符 "%d" 的含义 , 所以打印结果为 C 。
63. 
int a = 5, b = 4, c = 3, d = 2;
    if (a>b>c)
        printf("%d\n", d);
    else if ((c - 1 >= d) == 1)
        printf("%d\n", d + 1);
    else
        printf("%d\n", d + 1);
a>b>c求的是一个逻辑值,正确为1,错误为0,a=5,b=4,c=3,首先a>b成立,逻辑值为1,而1小于2,故不输出2;+或者-的优先级高于>=;所以c-1>=d先减再判断,成立,为逻辑值1;()优先级大于比较==,因为1=1,所以输出d+1;为3
64. 
因为负数的范围比正数大一个,比如8位的二进制,可以表示范围为-128~127所以abs(-128)可能并不能表示为128所以只能返回原值
65. 
因为const对象以及引用只能初始化而不能赋值,所以只能使用成员初始化列表。
对于非内置类型,在进入函数体之前,如果没有提供显式初始化,会调用默认构造函数进行初始化。若没有默认构造函数,则编译器尝试调用默认构造函数将会失败,所以如果没有默认构造函数,则必须在初始化列表中显示的调用构造函数。
static 成员在执行构造函数前就已经构造好了,即使不存在类对象,也可以被使用,不需要初始化列表
66. 
effective c++中,成员函数的const与nonconst可以构成重载
67. 
在主函数main中可以不写return语句,因为编译器会隐式返回0,但是在一般主函数中没有return语句是不行的。
68. 
int *p[] 是指针数组 ,一个数组里面存放着指针
int (*p)[]是数组指针,表示一个指针,指向整个数组
69. 
float (**def)[10];
def 是一个二级指针,它指向的是一个一维数组的指针,数组的元素都是float
double *(*gh)[10];
gh是一个指针,它指向一个一维数组,数组元素都是 double *.
double(*f[10])();
f是一个数组,f有10个元素,元素都是函数的指针,指向的函数类型是没有参数且返回double的函数
int *((*b)[10]);
就跟 int * (*b)[10] 是一样的,是一维数组的指针
long (*fun)(int)
函数指针
int (*(*F)(int,int))(int)
F是一个函数的指针,指向的函数的类型是有两个int 参数并且返回一个函数指针的函数,返回的函数指针指向有一个int参数且返回int的函数
70. 
迷途指针也叫悬浮指针,失控指针,是当对一个指针进行delete操作后,这样会释放它所指向的内存,并没有把它设置为空时而产生的。
71. 
S\065AB"字符串中包含S,\065(八进制数),A,B以及结束符\0
72. 
static的作用
1:设置静态局部变量,变量只定义一次,不能被别的函数使用
2:设置静态全局变量,变量不能被外部文件所使用
3:在类中设置静态函数,只能访问静态变量
73. 
因为静态成员存在于内存,非静态成员需要实例化才会分配内存,所以静态成员函数不能访问非静态的成员。因为静态成员存在于内存,所以非静态成员函数可以直接访问类中静态的成员
74. 
构造函数不能声明为虚函数,析构函数可以声明为虚函数,而且有时是必须声明为虚函数。
不建议在构造函数和析构函数里面调用虚函数。
构造函数不能声明为虚函数的原因是:
1 构造一个对象的时候,必须知道对象的实际类型,而虚函数行为是在运行期间确定实际类型的。而在构造一个对象时,由于对象还未构造成功。编译器无法知道对象 的实际类型,是该类本身,还是该类的一个派生类,或是更深层次的派生类。无法确定。。。
2 虚函数的执行依赖于虚函数表。而虚函数表在构造函数中进行初始化工作,即初始化vptr,让他指向正确的虚函数表。而在构造对象期间,虚函数表还没有被初 始化,将无法进行。
虚函数的意思就是开启动态绑定,程序会根据对象的动态类型来选择要调用的方法。然而在构造函数运行的时候,这个对象的动态类型还不完整,没有办法确定它到底是什么类型,故构造函数不能动态绑定。(动态绑定是根据对象的动态类型而不是函数名,在调用构造函数之前,这个对象根本就不存在,它怎么动态绑定?)
编译器在调用基类的构造函数的时候并不知道你要构造的是一个基类的对象还是一个派生类的对象。
析构函数设为虚函数的作用:
解释: 在类的继承中,如果有基类指针指向派生类,那么用基类指针delete时,如果不定义成虚函数,派生类中派生的那部分无法析构。
Note:
1. 如果我们定义了一个构造函数,编译器就不会再为我们生成默认构造函数了。
2. 编译器生成的析构函数是非虚的,除非是一个子类,其父类有个虚析构,此时的函数虚特性来自父类。
3. 有虚函数的类,几乎可以确定要有个虚析构函数。
4. 如果一个类不可能是基类就不要申明析构函数为虚函数,虚函数是要耗费空间的。
5. 析构函数的异常退出会导致析构不完全,从而有内存泄露。最好是提供一个管理类,在管理类中提供一个方法来析构,调用者再根据这个方法的结果决定下一步的操作。
6. 在构造函数不要调用虚函数。在基类构造的时候,虚函数是非虚,不会走到派生类中,既是采用的静态绑定。显然的是:当我们构造一个子类的对象时,先调用基类的构造函数,构造子类中基类部分,子类还没有构造,还没有初始化,如果在基类的构造中调用虚函数,如果可以的话就是调用一个还没有被初始化的对象,那是很危险的,所以C++中是不可以在构造父类对象部分的时候调用子类的虚函数实现。但是不是说你不可以那么写程序,你这么写,编译器也不会报错。只是你如果这么写的话编译器不会给你调用子类的实现,而是还是调用基类的实现。
7. 在 析构函数中 也不要调用虚函数。在析构的时候会首先调用子类的析构函数,析构掉对象中的子类部分,然后在调用基类的析构函数析构基类部分,如果在基类的析构函数里面调用虚函数,会导致其调用已经析构了的子类对象里面的函数,这是非常危险的。
8. 记得在写派生类的拷贝函数时,调用基类的拷贝函数拷贝基类的部分,不能忘记了。
75. 
预处理器发现#include后,就会寻找指令后面<>中的文件名,并把这个文件的内容包含到当前的文件中,被包含的文件中的文本将替换源代码文件中的#include指令
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值