1. 下面哪种面向对象的方法可以让你变得富有( B )
A: 继承 B: 封装 C: 多态 D: 抽象
(真·趣味题)a,期望你爸是李刚,但李刚未必有钱;乐观者选c,多态是在面向对象语言中,接口的多种不同的实现方式,保持开放的心态和广泛的人脉;有想 法的人选b,封装是在程序上,隐藏对象的属性和实现细节,仅对外公开接口,因其垄断,所以最有发财可能;梦幻者选d。
2. ( D )是面向对象程序设计语言中的一种机制。这种机制实现了方法的定义与具体的对象无关,
而对方法的调用则可以关联于具体的对象。
A: 继承 B: 模板 C: 对象的自身引用 D: 动态绑定
多态有两种:一种是函数重载实现静态绑定;一种是虚函数实现动态绑定
3. 面向对象设计中的继承和组合,下面说法错误的是?( C )
A:继承允许我们覆盖重写父类的实现细节,父类的实现对于子类是可见的,是一种静态复
用,也称为白盒复用
B:组合的对象不需要关心各自的实现细节,之间的关系是在运行时候才确定的,是一种动
态复用,也称为黑盒复用
C:优先使用继承,而不是组合,是面向对象设计的第二原则
D:继承可以使子类能自动继承父类的接口,但在设计模式中认为这是一种破坏了父类的封
装性的表现
4. 以下关于纯虚函数的说法,正确的是( A )
A:声明纯虚函数的类不能实例化对象 B:声明纯虚函数的类是虚基类
C:子类必须实现基类的纯虚函数 D:纯虚函数必须是空函数
声明纯虚函数的类是抽象类,虚基类虚拟继承中共享的基类;子类不一定要实现基类的虚基函数,只是子类重写这个虚基函数后才能正确的实例化出对象;空函数是不执行任何语句就返回的函数,显然纯虚函数不是空函数
5. 关于虚函数的描述正确的是( B )
A:派生类的虚函数与基类的虚函数具有不同的参数个数和类型 B:内联函数不能是虚函数
C:派生类必须重新定义基类的虚函数 D:虚函数可以是一个static型的函数
派生类的虚函数重写必须遵循三同:虚函数名,返回值,参数类型和个数,只有在协同的特殊情况下,返回值可以为父子类关系;inline 修饰的函数使用 virtual 修饰后,地址就会被放到虚表中去,因此不再具有内联特性;派生类可以不重新定义基类的虚函数;虚函数是通过对象的 this 指针来调用的,而 static 修饰的函数是属于这个类的,与任何实例对象都不相关。
6. 关于虚表说法正确的是( D )
A:一个类只能有一张虚表
B:基类中有虚函数,如果子类中没有重写基类的虚函数,此时子类与基类共用同一张虚表
C:虚表是在运行期间动态生成的
D:一个类的不同对象共享该类的虚表
多继承中可能会有多个虚表;子类如果没有重写虚函数,会将父类的虚表拷贝下来,且虚表是在编译阶段生成的,只是虚函数表指针是在运行时被赋值的,虚表是属于这个类的,实例化出的对象共用这个虚表
7. 假设A类中有虚函数,B继承自A,B重写A中的虚函数,也没有定义任何虚函数,则( D )
A:A类对象的前4个字节存储虚表地址,B类对象前4个字节不是虚表地址
B:A类对象和B类对象前4个字节存储的都是虚基表的地址
C:A类对象和B类对象前4个字节存储的虚表地址相同
D:A类和B类虚表中虚函数个数相同,但A类和B类使用的不是同一张虚表
每个类都有自己独有的虚表,用自己的虚函数表指针来访问,地址都是不一样的。
8. 什么是菱形继承?菱形继承的问题是什么?
菱形继承是是多继承的一种特殊情况:当一个子类(派生类)直接或间接同时继承了两个父类(基类),而这个两个父类(基类)又直接或间接继承自同一个父类(基类),从而形成了一份菱形的继承关系。
问题:菱形继承中,派生类(子类)存储了两份基类(父类)数据的问题,会导致数据访问的二义性问题(不明确访问的是哪一个),和数据冗余问题(同一份数据存了两份)
9. 什么是菱形虚拟继承?如何解决数据冗余和二义性的
在继承中使用虚拟继承来解决菱形继承导致的一些问题。
如何解决:在虚拟继承发生菱形继承的派生类的基类中,每个基类在虚拟继承时都添加了一个指针,这个指针指向一个表,叫虚基表,虚基表中存储的是基础基类的成员相对于这两个指针的偏移量,利用这两个虚表中的偏移量通过指针访问的是同一个基础基类的成员变量。访问的是同一个成员,就解决数据二义性的问题;只存一份,通过指针指向虚表的偏移量去访问,就解决了数据冗余问题。
10. 继承和组合的区别?什么时候用继承?什么时候用组合?
继承是一种 is - a 的关系,即每一个派生类对象都是一个基类对象;而组合是一种 has - a 的关系,如果类 A 组合了类 B,那么每一个 A 对象中都有一个 B 对象。继承是一种白箱复用,父类的内部细节大多对子类是透明的,耦合度较高;组合是一种黑箱复用,另一个类的内部细节在组合时被隐藏,类之间没有很强的依赖关系,耦合度低,利于类的封装。
当两个类之间符合 is - a 的关系时用继承(学生(子类)是人(父类));当两个类之间的关系符合 has - a 的关系时用组合。使用继承还是组合具体取决于两个类之间的关系,适合什么用什么,如果两个关系都符合,优先使用组合,可维护性较高!