高程押题
题型
一、简述题
二、程序分析题
三、编程题
简述题押题
第六章
- 程序设计中,多态性通常表现为什么:重载(函数名重载和操作符重载),类属(类属函数和类模板),对象类型的多态,对象标识的多态,消息的多态。
- 不能把未定义好的类的对象作为数据成员,为什么:不能确定其占有的内存空间/递归定义
- 类的定义中不能赋初值:类中说明的数据成员并不占有内存空间
- 动态对象为什么不用malloc和free:malloc只能申请一段内存返回地址,不能自动执行构造函数,free同理
- 什么才算默认构造函数:无参数或者所有参数有默认值的构造函数
- 构造函数有可能是private访问控制的嘛:有可能,此时只能在类内部或者友元中创建对象
- 什么情况下一定要使用成员初始化表:1)非静态常量数据成员的初始化;2) 引用成员的初始化;3)初始化没有默认构造函数的成员对象;4) 基类私有数据成员的初始化
- 为什么成员初始化表的顺序是按类中定义的说明次序:成员变量在使用初始化列表初始化时根据变量在内存中的顺序,这个顺序是由变量定义次序决定的
- 以String类为例,析构函数中什么情况下要把指针设为空指针:显式调用析构函数的时候
- 成员对象的初始化和消亡具体是怎样进行的:编译程序把成员初始化表中对成员对象的初始化编译成对成员对象构造函数的调用指令,在创建含有成员对象的类的对象时先调用本类的构造函数,但在进入本类构造函数体前会先调用成员对象构造函数,再执行本类构造函数的函数体。如果成员初始化列表为空,则调用成员对象的默认构造函数。如果本类没有任何构造函数,那么编译程序会隐式构造一个默认构造函数,目的就是去调用成员对象的构造函数。初始化顺序类似第9题描述。消亡时,先调用本类析构函数,执行完毕后再调用成员对象的析构函数,总之次序与构造函数的调用顺序相反,如果本类没有任何析构函数,那么编译程序会隐式构造一个默认析构函数,目的就是去调用成员对象的析构函数。
- 拷贝构造函数在什么情况下会调用:定义对象时、作为值参数时、作为值返回时
- 在自定义拷贝构造函数时应该注意什么:参数表基本都长成(const A& a)这个样子。不会调用成员对象的拷贝构造函数,应该在自定义拷贝构造函数的成员初始化表中显式指出。
- 如果用一个临时对象作为值参数传进函数或者函数返回一个临时对象值,编译器会如何进行优化:不再创建形参对象,直接把临时对象传进去;不再创建返回值对象,直接把临时对象返回
- 把对象传给函数的时候为什么常传入指针/引用,此时需要注意什么:提高参数的传递效率;加一个const防止通过指针/引用修改了原值
- 常成员函数的作用:防止获取对象状态时误修改了对象的状态;告诉编译程序该成员函数不会改变对象数据成员的值(常量对象只能访问常成员函数!)
- 静态数据成员的定义、初始化有什么特点:在类的外部给出(特别的,int和enum静态可以直接在类定义中初始化)
- 静态成员函数有什么特点:只能访问静态成员、没有this指针作为参数、调用时不需知道某个具体对象,把类看作对象,把类定义的静态成员看作属于类这个对象。
- 友元的类型:友元函数、友元类、友元类成员函数
- 重载双目操作符时有时只能用全局函数:重载的第一个操作数的类型和本类不匹配
- 怎么实现单目操作符后置用法:参数中加一个int
- 什么情况下我们需要重载new和delete,重载时需要注意什么:系统堆内存的管理效率是不高的,因为他会面临“碎片”问题,而存储空间的移动需要花费大量时间。我们有时基于这样一个思想进行重载:创建第一个对象时申请一块大空间,然后划分为若干小空间,链表连接,除非空间不够或者程序结束时才去堆内存申请或者归还。程序实现要会!重载时,遵循格式:void* operator new(size_t size); void operator delete(void* p)
- 对动态对象数组的创建和撤销的重载需要注意什么:遵循格式void* operator new[](size_t size); void operator delete[](void* p);如果类中有析构函数,那么new函数的size得到的值会比数组的实际大小多4个字节,用来存储数组元素的个数,以便delete时知道有多少个对象,从而针对每个对象调用它们的析构函数(太人性化辣!)
- 怎么理解智能指针:智能指针往往需要重载'->',它应该返回一个正常的指针,这样p->f()会变成p.opreator()->f()
- 类型转换操作符有几种情况,需要注意什么:带一个参数的构造函数、自定义类型转换;可能产生歧义
第七章
- 定义派生类时一定要见到基类的定义:否则编译程序无法确定派生类对象占用多大内存以及派生类对基类成员的访问是否合法
- 派生类对象的初始化和消亡要注意什么:顺序呗!直接来最复杂的情况:如果一个类既有基类又有成员对象类,则在创建该类对象时先调用基类的构造函数,再调用成员对象的构造函数,最后执行自己的函数体;消亡时先调用和执行自己的析构函数,再调用成员对象的析构函数,最后调用基类的构造函数
- 对于派生类对象消息的动态绑定,会绑定到派生类中与基类虚函数具有相同型构的成员函数,这里的相同型构指什么:名字参数类型个数返回值类型都和基类的那个函数相同
- 构造函数不能是虚函数,析构函数往往是虚函数,为什么:
- 在构造函数中调用虚函数不会动态绑定的原因:基类构造函数先于派生类构造函数体执行,在基类构造函数执行时,派生类中的数据成员还未初始化,这时如果调用派生类的成员函数将会导致在未初始化的数据上进行操作,从而产生一些不确定的结果。析构函数中调用虚函数不会动态绑定的原因:析构函数是用来销毁一个对象的,在销毁一个对象时,先调用派生类的析构函数,然后再调用基类的析构函数。所以在调用基类的析构函数时,派生类对象的数据成员已经“销毁”,这个时再调用子类的虚函数已经没有意义了。
- 纯虚函数的用处:创建抽象类为派生类提供框架和接口;隐藏类的定义防止通过指针绕过访问控制访问到数据成员
- 多继承中基类的声明次序决定了:基类成员存储安排、基类构造函数/析构函数的调用次序
- 对于包含虚基类的类要注意什么:虚基类的构造函数由该类的构造函数直接调用且优先执行(原因:保证虚基类的成员只被初始化一次)
- 聚合类成员对象/组合类对象有什么区别
第八章
- 对<<、>>的重载要注意什么
第九章
- 关于try\throw\catch要注意些什么
- assert断言的实现细节中,如何让编译时assert不再有效:让NDEBUG有定义
第十章
- 由于c++中源文件是分别编译的,因此如果一个源文件中定义并实现了一个模板,但该源文件中未用到该模板的某个实例,则在相应的目标文件中编译程序不会生成该模板相应实例的代码。解决方法:把模板的定义和实现都放在某个头文件中,在需要使用模板的源文件中包含该头文件。
- 使用算法对容器中的元素操作时要注意:
- 为什么尾递归不会出现栈溢出:递归调用完后就用不到本次执行的栈空间内容,这样递归
- 过滤调用归约

浙公网安备 33010602011771号