《程序员面试宝典》精华 面向对象部分
- 正所谓取其精华,去其糟粕。本文谨记录下《程序员面试宝典》一些关键的知识点、易错点,对于一些虽然重要但书中没有解释清楚的地方不做记录。书里是没有糟粕的,只是指不那么重要,或者比较简单的地方略过而已,并不是说书写的不好。希望以后回顾时无需再看此书,只看保留在文中的精华即可。
- 文中有少许bug,亦摘录在此。
- 本文专注面向对象部分,包括第十章到第十一章的内容
第十章 面向对象
- 10.2 类与结构体的区别:都能继承、拥有析构等成员函数,唯一的区别是struct成员默认为public,而class默认为private。C++是为了兼容C代码才保留struct关键字
- 10.3
class B{...}; B b(); b.f();
是错误的,b声明为了一个函数 - 10.3 静态成员变量必须显式初始化,例如
int A::i 0;
- 10.3 成员变量初始化顺序与初始化列表顺序无关,与变量声明顺序有关
- 10.3 常数(cosnt)成员变量必须中构造函数的初始化列表里面初始化,或者声明为
static const
成员 - 10.4 把成员函数声明为虚函数造成调用开销增大,为什么常常把基类的析构函数声明为虚函数:多态情况下常常把派生类对象的指针赋给基类指针,那么使用虚函数保证delete时能调用派生类对象的析构函数,而不造成内存泄露
- 10.4 构造函数为什么不能声明为virtual:虚调用是来调用一个只知道接口而不知道其对象类型的成员函数,实例化对象时必须知道对象的准确类型,因此构造函数不能为virtual(存疑,不够clear)
- 10.4 函数f返回一个对象时,使用
A t = f()
,会调用拷贝构造函数。即函数参数和返回值都是对象时,都会调用一次拷贝构造函数 - 10.4 含有单个参数的构造函数会定义一个从参数类型到类的隐式类型转换,使用explicit关键字可以避免此转换
- 10.5 函数参数常声明为const,这是因为const变量不能随意转换为非const,反之则可
- 10.5 要求类的每个对象有唯一id,需要自定义拷贝构造函数避免重复
- 10.5 如果类包含动态分配的指针,那么需要定义拷贝构造函数和赋值函数
- 10.6 什么是多态?
- 概念:封装、继承、多态是OO的三大基本概念。多态指的是允许将子类类型赋值给父类指针,而父类指针可以通过统一的接口对所有子类对象进行操作
- 作用与目的:封装为了隐藏实现细节,以及数据类型和函数的统一,模块化;继承是为了方便扩展已有的代码模块;两者均可实现代码重用,而多态是为了实现接口重用
- 实现方法:虚函数
- 10.6 重写与重载,前者override是指子类重新定义父类的虚函数,后者overload是指同时存在多个参数列表不同的同名函数
第十一章 继承与接口
- 11.1 如果显式调用虚函数,则虚调用机制失效,如
class B::public A{}; B b; b.A::f();
,类f为虚函数,但此时显式调用A中的f - 11.2 三种继承方式的区别
- public继承:基类的public和protected成员对基类保持原有状态
- 基类成员对派生类的可见性:派生类(的成员函数)可以访问基类的public和protected成员
- 基类成员对派生类对象的可见性:(通过)派生类的对象(指例如
a.f()的方式
)可以访问基类的public成员
- private继承:将基类的public和protected成员当成派生类的private成员,且不能被派生类的子类访问
- 基类成员对派生类的可见性:派生类(的成员函数)可以访问基类的public和protected成员
- 基类成员对派生类对象的可见性:(通过)派生类的对象不可以访问基类的任何成员,因此基类的成员无法再向下继承
- protected继承:将基类的public和protected成员当成派生类的protected成员,且不能被派生类的子类访问
- 基类成员对派生类的可见性:派生类(的成员函数)可以访问基类的public和protected成员
- 基类成员对派生类对象的可见性:(通过)派生类的对象不可以访问基类的任何成员,因此基类的成员无法再向下继承
- 关键差别在于通过派生类对象可以访问基类的哪些成员,以及派生类的子类能否访问派生类的成员
- public继承:基类的public和protected成员对基类保持原有状态
- 11.2 三种成员属性的区别:基类的private成员对派生类屏蔽,protected成员使派生类可以访问,基类仅有public成员可以通过基类的对象访问
- 11.2 虚继承是为了解决多重继承中的菱形继承冲突,派生类中会添加一个指向基类虚函数表的指针
- 例如,C、B虚继承自A,D继承自B、C,则D中共有1个A
- 11.4 Java中使用接口替代多重继承,C++可以使用抽象类模拟接口
- 11.4 C继承自A,B,pC指向C对象,pB把pC转换为指向B的指针,则
pC == pB
,这里发生从C的指针到B的指针的隐式转换,书中说反了,bug - 11.5 类的继承默认为private,通常需要加public关键字
- 11.6 如何防止一个类实例化:使用带有纯虚函数的抽象类,或者把构造函数声明为private
- 11.7 RTTI的缺点:除了运行开销外,使程序变得不确定,缺乏扩展性
- 11.7 类型转换运算符重载,无返回值无参数,以目标类型为函数名,如:
operator char*()
- 11.8 dynamic_cast如果转换失败返回0
- 11.8 typeid返回值为对type_info常量对象的引用